#include<iostream> usingnamespace std; int a[1000], v[1000], n, k; //A (n,k) voiddfs(int cnt, int num) { for (int i = 1; i <= n; i++) //组合 for(int i = num+1; i <= n ;i++) if (!v[i]) { a[cnt] = i; v[i] = 1; if (cnt == k) // 边界条件 { // 得到一个结果 // for (int i = 1; i <= k; i++) // cout << a[i]; // cout << endl; } else dfs(cnt + 1, i); v[i] = 0; } } intmain() { cin >> n >> k; dfs(1, 0); return0; }
这个方法只能生成数据为 1~n 的结果,而如果原始数据不是前 n 个数字的话,可以使用索引的方法,即 cout << data[a[i]];
使用递归(法二,推荐)
这个方法就是书上的了,我测下来效果是最好的,基本思想就是拿每一层的第一个数跟后面的数依次交换
1 2 3 4 5 6 7 8 9 10 11 12 13
intPerm(int begin, int end) { if (begin == end) // 得到一个结果 return1; int sum = 0; for (int i = begin; i <= end; i++) { swap(data[begin], data[i]); sum += Perm(begin + 1, end); swap(data[begin], data[i]); } return sum; }
这个 swap() 不建议使用 STL 里面的,建议自己写函数,当然最快的当然是使用宏 #define swap(a, b) {int t = a; a = b; b = t; }
如果原始数据不是 int ,而是一些比较大的类型(直接 swap() 比较慢),可以考虑上面讲的索引的方法,先把索引数组构造出来,然后再索引原始数据
跑了一遍测试 P1212,速度差别比较明显(依次为三种方法)
1 2 3 4 5 6
sum = 479001600 14.138 sum = 479001600 27.141 sum = 479001600 5.653
#include<bits/stdc++.h> usingnamespace std; voidprint_subset(int n, int m) { for (int i = 0; i < (1 << n); i++) { int num = 0, kk = i; while (kk) { kk = kk & (kk - 1); num++; } if (num == m) { for (int j = 0; j < n; j++) { if (i & (1 << j)) cout << j << " "; } cout << endl; } } } intmain() { int n, m; cin >> n >> m; print_subset(n, m); return0; }