1. 程式人生 > >NOI2.2基本演算法之遞迴和自呼叫函式 全排列 分析----如何寫全排列函式

NOI2.2基本演算法之遞迴和自呼叫函式 全排列 分析----如何寫全排列函式

一、題目描述

總時間限制: 
1000ms 
記憶體限制: 
65536kB
描述
給定一個由不同的小寫字母組成的字串,輸出這個字串的所有全排列。

我們假設對於小寫字母有'a' < 'b' < ... < 'y' < 'z',而且給定的字串中的字母已經按照從小到大的順序排列。
輸入
輸出只有一行,是一個由不同的小寫字母組成的字串,已知字串的長度在1到6之間。
輸出
輸出這個字串的所有排列方式,每行一個排列。要求字母序比較小的排列在前面。字母序如下定義:

已知S = s1s2...sk , T = t1t2...tk,則S < T 等價於,存在p (1 <= p <= k),使得
s1
 = t1, s2 = t2, ..., sp - 1 = tp - 1, sp < tp成立。
樣例輸入
abc
樣例輸出
abc
acb
bac
bca
cab
cba
二、分析 這一道題可以用遞迴來解決,題目中說過“給定的字串中的字母已經按照從小到大的順序排列”,所以我們不用進行字串處理,可以直接將字串輸入,再寫函式。因為字串的長度為1~6,所以我們定義一個字元陣列“char a[10];”(原陣列),再定義字元陣列"c[10]"(填寫陣列),定義一個整型變數“int l;”(長度)。(全域性變數)
  • #include<cstdio>
  • #include<cstring>
  • char a[10],c[10];
  • int l;
  • 再寫主函式
  • int main()
  • {
gets(a);l=strlen(a);f(0);//從字元陣列第0個開始填寫
  • }
  • 接下來,就開始寫函式
  • void f(int k)
  • {
for(i=0;i<l;i++){...
}
}
  • 為了記錄字元陣列a中的元素是否被訪問,我們可以定義一個v陣列“bool v[10];”
  • bool v[10];
  • void f(int k)//k指目前c陣列要填的元素
  • {
for(i=0;i<l;i++){if(!f[i]){f[i]=1;//1為訪問,0為沒有訪問c[k]=a[i];//將c陣列中的第k個元素填入f(k+1);//繼續填下一個元素f[i]=0;//將訪問了的元素恢復}
}
}
  • 這一個函式沒有邊界
      • void f(int k)
      • {
if(k==l){//填滿了(即邊界)printf("%s\n",c);return;
}for(i=0;i<l;i++){if(!f[i]){f[i]=1;c[k]=a[i];f(k+1);f[i]=0;}
}
} 終於大功告成了。三、另解 後來才知道全排列函式“next_permutation()”,其用法自己上網搜,非常簡單,很有用。