(一)生成1~n的排列
分析:用递归的思想解决:先输出所有以1开头的排列(这一步是递归调用),然后输出以2开头的排列(又是递归调用),接着是以3开头的排列......最后才是以n开头的排列。
伪代码:
void print_permutation(序列A, 集合S) {
if(S为空) 输出序列A;
else 按照从小到大的顺序依次考虑S的每个元素v {
print_permutation(在A的末尾填加v后得到的新序列,S-{v});
}
}
下面是实现代码:
#include <iostream> using namespace std; const int MAXN = 1000; int A[MAXN], n; void print_permutation(int n, int *A, int cur) { if(cur == n) { //递归边界 for(int i = 0; i < n; ++i) cout << A[i] << " "; cout << endl; }else { for(int i = 1; i <= n; ++i) { //尝试在A[cur]中填各种整数i int ok = 1; for(int j = 0; j < cur; ++j) { if(A[j] == i) ok = 0; //如果i已经在A[0]~A[cur-1]出现过,则不能再选 } if(ok) { //i在A[0]~A[cur-1]<span style="font-family: Arial, Helvetica, sans-serif;">中没有出现过,所以可以把i放进A[cur]</span> A[cur] = i; print_permutation(n, A, cur+1); //递归调用 } } } } int main() { cin >> n; print_permutation(n, A, 0); return 0; }
(二)生成可重集的排列
输入数组P,按照字典序输出数组P各元素的所有全排列。
#include <iostream> #include <algorithm> using namespace std; const int MAXN = 1000; int A[MAXN], P[MAXN], n; void print_permutation(int n, int *P, int *A, int cur) { if(cur == n) { for(int i = 0; i < n; ++i) cout << A[i] << " "; cout << endl; }else for(int i = 0; i < n; ++i) if(!i || P[i] != P[i-1]){ //if条件句确保了不会重复递归调用相同的元素,保证了我们枚举的下标i应不重复不遗漏地取遍所有P[i]值 int c1 = 0, c2 = 0; for(int j = 0; j < cur; ++j) if(P[i] == A[j]) c1++; //A[0]~A[cur-1]中P[i]出现的次数放在c1中 for(int j = 0; j < n; ++j) if(P[i] == P[j]) c2++; //P数组中P[i]的出现次数放在c2中。 if(c1 < c2) { //只要c1<c2就能递归调用,这样就保证了不会遗漏相同的元素。 A[cur] = P[i]; print_permutation(n, P, A, cur+1); } } } int main() { cin >> n; for(int i = 0; i < n; ++i) cin >> P[i]; sort(P, P+n); print_permutation(n, P, A, 0); return 0; }
(三)生成下一个排列:
枚举所有排列的另一个方法是从字典序最小排列开始,不停的调用“求下一个排列”的过程。
利用STL里面的next_permutation来求下一个排列,
#include <iostream> #include <cstdio> #include <algorithm> #define MAXN 1000 using namespace std; int P[MAXN]; int main(){ int n; cin >> n; for(int i = 0; i < n; ++i){ cin >> P[i]; } sort(P, P+n); // 排序,得到p的最小排列 do{ for(int i = 0; i < n; ++i){ cout << P[i] << " "; } cout << endl; }while(next_permutation(P, P+n)); return 0; }
ACM:回溯法,枚举排列
时间: 2024-12-28 00:45:49