遞迴實現組合型列舉
阿新 • • 發佈:2020-08-24
題目描述
從 1~n 這 n 個整數中隨機選出 m 個,輸出所有可能的選擇方案。
輸入格式
兩個整數 n,m ,在同一行用空格隔開。
輸出格式
按照從小到大的順序輸出所有方案,每行1個。
首先,同一行內的數升序排列,相鄰兩個數用一個空格隔開。
其次,對於兩個不同的行,對應下標的數一一比較,字典序較小的排在前面(例如1 3 5 7排在1 3 6 8前面)。
資料範圍
n>0
0\(\leq\) m \(\leq\) n
n+(n-m) \(\leq\) 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
思路
跟上一篇題解遞迴實現指數型列舉的思想基本一致。採取深度優先搜尋。
對於1~n
的每一個數字都有選與不選兩種情況。當選擇每一個數字時,相應的計數器都ans
會加1。當ans==m
時,輸出選擇的數字即可。
具體細節請見與程式碼註釋。
遞迴C++ 程式碼
#include<iostream> using namespace std; int n,m; int stu[30]; void dfs(int u,int ans) { if(u>n+1)//這時的選擇的數字範圍已經不在1~n之間了。為了防止程式陷入死迴圈應當及時結束函式 return; if(ans>=m)//將選擇的m個數字輸出 { for(int i=1;i<=n;i++) if(stu[i]==1) cout<<i<<" "; cout<<endl; return; } stu[u]=1;//選擇數字u dfs(u+1,ans+1);//在選擇數字u的基礎上進行深度優先遍歷,這時因為選擇了數字u,應當使ans+1. stu[u]=0;//回溯,消除選擇數字u帶來的影響,便於接下來對不選擇數字u進行操作 stu[u]=2;//不選擇數字u dfs(u+1,ans);//不在選擇數字u的基礎上進行深度優先遍歷,這時因為沒有選擇數字u,應當時ans保持不變. stu[u]=0;//回溯,消除沒有選擇數字u帶來的影響,便於接下來的操作 } int main() { ios::sync_with_stdio(false);//關閉輸入流同步,提高讀寫效率 cin.tie(0); cin>>n>>m; dfs(1,0);//從數字1開始進行深度優先遍歷 return 0; }
思考題
如果要求使用非遞迴方法,該怎麼做呢?