『算法-ACM 竞赛-算法-枚举法』信息竞赛进阶指南-枚举方法
你以为枚举是一个一个的找?
还真是
你以为枚举都是 for 循环?
还真是
但你真的会枚举吗?组合型枚举,指数型枚举,排列型枚举?难道你只会线形枚举?
你可太菜了!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
| vector<int> chosen; void calc(int x) { if (x == n + 1) { for (int i = 0; i < chosen.size(); i++) printf("%d ", chosen[i]); puts(""); return; } calc(x + 1); chosen.push_back(x); calc(x + 1); chosen.pop_back(); }
vector<int> chosen; void calc(int x) { if (chosen.size() > m || chosen.size() + (n - x + 1) < m) return; if (x == n + 1) { for (int i = 0; i < chosen.size(); i++) printf("%d ", chosen[i]); puts(""); return; } calc(x + 1); chosen.push_back(x); calc(x + 1); chosen.pop_back(); }
int order[20]; bool chosen[20]; void calc(int k) { if (k == n + 1) { for (int i = 1; i <= n; i++) printf("%d ", order[i]); puts(""); return; } for (int i = 1; i <= n; i++) { if (chosen[i]) continue; order[k] = i; chosen[i] = 1; calc(k + 1); chosen[i] = 0; order[k] = 0; } }
vector<int> chosen; int stack[100010], top = 0, address = 0;
void call(int x, int ret_addr) { int old_top = top; stack[++top] = x; stack[++top] = ret_addr; stack[++top] = old_top; }
int ret() { int ret_addr = stack[top - 1]; top = stack[top]; return ret_addr; }
int main() { int n, m; cin >> n >> m; call(1, 0); while (top) { int x = stack[top - 2]; switch (address) { case 0: if (chosen.size() > m || chosen.size() + (n - x + 1) < m) { address = ret(); continue; } if (x == n + 1) { for (int i = 0; i < chosen.size(); i++) printf("%d ", chosen[i]); puts(""); address = ret(); continue; } call(x + 1, 1); address = 0; continue; case 1: chosen.push_back(x); call(x + 1, 2); address = 0; continue; case 2: chosen.pop_back(); address = ret(); } } }
|