dfs 遞迴思想 解決排列組合的一些基礎問題
阿新 • • 發佈:2019-01-29
對於搜尋的深度很深或深度不固定的情況,則無法用列舉的方法來設定迴圈巢狀的層數,這時可以考慮用遞迴法來完成搜尋任務。遞迴是一種常用演算法,它是搜尋的另一種實現方式。如果在演算法設計中採用一個函式或過程直接或間接地呼叫它自身來解決問題的方法,則稱該方法為遞迴演算法。遞迴演算法必須要設計好一個或若干個確定的遞迴終止條件。
一......
Sample Input
4 2 //用0,1組合出四個數字來
Sample Output
0000 0001 0010 0011 0100 0101
0110 0111 1000 1001 1010 1011
1100 1101 1110 1111
#include<stdio.h> int n,m,ans; int mat[10]; void solve(int l) { if(l>=n) { for(int i=0;i<n;++i)printf("%d", mat[i]); puts(""); ans++; return ; } for(int i=0;i<m;++i) { mat[l]=i; solve(l+1); } } int main() { while(scanf("%d%d", &n, &m)!=EOF) { ans=0; solve(0); printf("%d\n",ans); } return 0; }
二全組合排列(沒有去重,沒有考慮0的問題)
三非重複組合排列(含重複數字時,生成不重複組合排列,並且0也不能放在首位)#include<stdio.h> #include<string.h> const int maxn=11; int n; int used[maxn];//標記陣列 int mat[maxn];//儲存陣列 int num[maxn];//輸出陣列 void solve(int l) { if(l>=n) { for(int i=0;i<n;++i)printf("%d", num[i]); puts(""); return; } for(int i=0;i<n;++i) { if(!used[i]) { used[i]=1; num[l]=mat[i]; solve(l+1); //遞迴 used[i]=0; //回溯 } } } int main() { while(scanf("%d", &n)!=EOF) { for(int i=0;i<n;++i) scanf("%d", mat+i); memset(used,0,sizeof(used)); solve(0); } return 0; }
#include <cstdio> #include <cstring> const int maxn = 10; int n,v,ans; int used[maxn],a[maxn],num[maxn]; void push(int v) { for(int i = 0 ; i < ans ; i++) { if(a[i]==v) { ++used[i]; return ; } } a[ans]=v; ++used[ans++]; //ans為不重複的數字的個數 //used[i]儲存的是i出現的次數 } void solve(int l) { if(l>=n) { for(int i = 0 ; i < n ; i++)printf("%d",num[i]); puts(""); } for(int i = 0 ; i < ans ; i++) { if(l==0&&a[i]==0)continue; if(used[i]) { used[i]--; num[l]=a[i]; solve(l+1); used[i]++; } } } int main() { while(scanf("%d", &n)!=EOF) { memset(used,0,sizeof(used)); ans=0; for(int i=0;i<n;++i) { scanf("%d", &v); push(v); } solve(0); } return 0; }