全排列 dfs
阿新 • • 發佈:2018-12-24
全排列
給出一個字串S(可能有重複的字元),按照字典序從小到大,輸出S包括的字元組成的所有排列。例如:S = "1312",
輸出為:
1123
1132
1213
1231
1312
1321
2113
2131
2311
3112
3121
3211
1. 先寫一發簡單的(直接套用C++標準庫中提供的next_permutation函式,將n個元素共n!種不同的排列生成出來)
2. dfs的簡單應用,可以拿來練習dfs 思路:把數儲存在陣列a中,不斷放入陣列b中形成全排列,再將b輸出即可。 比如有123, a[0]=1,a[1]=2,a[2]=3, 放入b中: 第一種: 將1放入b中,即b[0]=1, 依次有 b[1]=2, b[2]=3,此時b的長度和a的長度相等也就是b已經放滿,可以將此結果輸出 第二種: 在第一種回退(回溯),b[0]=1,b[1]=2,b[2]清除,但此時3還是隻能放在b[2],所以只能繼續回溯,將b[2]清除 b[0]=1,b[1]=3,b[2]=2,這是第二種情況 第三種: 在第二種基礎上回溯,直到回溯到b[0] ,得出b[0]=2,b[1]=1,b[2]=3(因為要求是字典序,故數值小的數優先放在前面) ......(依次類推)
#include<iostream> #include<algorithm> #include<cstring> using namespace std; char s[12]; int a[12]={0}; int len; void input() { cin>>s; len=strlen(s); for(int i=0;i<len;i++) //將字串中的數字找出來放入a中 a[i]=(int)(s[i]-'0'); sort(a,a+len); //排序 } int main() { input(); do { for(int i=0;i<len;i++) cout<<a[i]; cout<<endl; }while(next_permutation(a,a+len)); return 0; }
2. dfs的簡單應用,可以拿來練習dfs 思路:把數儲存在陣列a中,不斷放入陣列b中形成全排列,再將b輸出即可。 比如有123, a[0]=1,a[1]=2,a[2]=3, 放入b中: 第一種: 將1放入b中,即b[0]=1, 依次有 b[1]=2, b[2]=3,此時b的長度和a的長度相等也就是b已經放滿,可以將此結果輸出 第二種: 在第一種回退(回溯),b[0]=1,b[1]=2,b[2]清除,但此時3還是隻能放在b[2],所以只能繼續回溯,將b[2]清除 b[0]=1,b[1]=3,b[2]=2,這是第二種情況 第三種: 在第二種基礎上回溯,直到回溯到b[0] ,得出b[0]=2,b[1]=1,b[2]=3(因為要求是字典序,故數值小的數優先放在前面) ......(依次類推)
#include<iostream> #include<algorithm> #include<cstring> using namespace std; int a[12]; int b[12]; int vis[12]; char s[12]; int len; void dfs(int s) { if(s==len) { for(int i=0;i<len;i++) cout<<b[i]; cout<<endl; return; } else { for(int i=0;i<len;i++) { if(!vis[i]) { vis[i]=1; b[s]=a[i]; dfs(s+1); vis[i]=0; //回溯 將已經標記訪問過的標記清除 while(a[i]==a[i+1]) i++; //去重 (比如有三個1,三個1無所謂誰前誰後) } } } } int main() { cin>>s; memset(a,0,sizeof(a)); memset(vis,0,sizeof(vis)); len=strlen(s); for(int i=0;i<len;i++) a[i]=(int)(s[i]-'0'); sort(a,a+len); //排序 dfs(0); return 0; }