從?1~n?這?n?個整數中隨機選出?m?個,輸出所有可能的選擇方案。
輸入格式
兩個整數?n,m,在同一行用空格隔開。
輸出格式
按照從小到大的順序輸出所有方案,每行?1?個。
首先,同一行內的數升序排列,相鄰兩個數用一個空格隔開。
其次,對于兩個不同的行,對應下標的數一一比較,字典序較小的排在前面(例如?1 3 5 7
?排在?1 3 6 8
?前面)。
數據范圍
n>0?,
0≤m≤n?,
n+(n?m)≤25
輸入樣例:
5 3
輸出樣例:
1 2 3
1 2 4
1 2 5
1 3 4
1 3 5
1 4 5
2 3 4
2 3 5
2 4 5
3 4 5
題目鏈接:93. 遞歸實現組合型枚舉 - AcWing題庫
學習鏈接:遞推與遞歸 + DFS | 手把手帶你畫出遞歸搜索樹_嗶哩嗶哩_bilibili?
解題思路:?
- 保證所有方案按字典序排序,且一個方案中后一個元素比前一個元素大
- 解決方案:每枚舉到一個新位置,試探起始元素比前一個位置的元素+1
- 設置一個桶t[],容量為m個元素,裝未被試探過且比前一個位置中的元素大的數
- 設置一個visited[],標記已訪問過的元素(這題不用設置也可以)
- 得到一個方案后,即桶t[]裝夠了m個元素,結束搜索
- 重復 "撤出-裝入" 這一操作,即回溯-搜索,撤出元素是為了騰出位置便于得到新的方案(在不同位置放置不同的元素),重新標記撤出的元素為未訪問過?
代碼如下:
#include<bits/stdc++.h>
using namespace std;
int n;//總元素個數
int m;//方案中元素個數
int t[30];//記錄方案結果
int visited[30];//0 未訪問,1 已訪問void dfs(int pos,int start)
{//剪枝:當可選元素數量(n-start+1)<空位置數量(m-pos+1)時,咔擦掉(這題不剪也可以過) if(n-start+1<m-pos+1) return ;//直接結束搜索 //如果方案中所枚舉數量超過m個,終止搜索 if(pos>m){//輸出方案for(int i=1;i<=m;i++)cout<<t[i]<<" ";cout<<endl;return ;//結束枚舉 }for(int i=start;i<=n;i++){//這題不用設置visited[]t[pos]=i;//對下一個位置進行枚舉,下一個位置的起始元素要比該位置的元素大dfs(pos+1,i+1);//撤出元素,便于新方案的選擇t[pos]=0; }
}
int main()
{cin>>n>>m;dfs(1,1);//從第一個位置且起始元素為 1 開始枚舉方案 return 0;
}
?希望能幫助到各位同志,祝天天開心,學業進步!