--- ###### tags: `2021 師大附中資訊科暑期培訓` --- # 枚舉 2021 師大附中資訊科暑期培訓 joylintp --- ## 密密麻麻密碼鎖 ### NPSC 2017 國中決賽 ---- 有一個六位數的密碼鎖 現在上面顯示的數字為 $\overline{abcdef}$ 每次操作你可以把其中一位數加上1或減去1 (9加上1變成0;0減去1變成9) 求至少要 $k$ 次操作才能使六位數字皆相異 並列出所有 $k$ 次操作後六位數字皆相異的可能狀態 ---- ~~遞迴~~ ~~動態規劃~~ ### 窮舉 ---- ```cpp= #include<bits/stdc++.h> using namespace std; int main() { ios_base::sync_with_stdio(false); cin.tie(0); int n; cin >> n; int mn = 2147483647; set<int> anslist; for (int i = 12345; i < 1000000; i++) { int t = i, u; set<int> s; if (i < 100000) s.insert(0); while (t) s.insert(t % 10), t /= 10; int tmp = 0; if (s.size() == 6) { t = i; u = n; while (t || u) tmp += min(abs(t % 10 - u % 10), 10 - abs(t % 10 - u % 10)), t /= 10, u /= 10; if (tmp < mn) anslist.clear(), anslist.insert(i), mn = tmp; else if (tmp == mn) anslist.insert(i); else; } } cout << anslist.size() << ' ' << mn << '\n'; for (int i : anslist) cout << setw(6) << setfill('0') << i << ' '; return 0; } ``` --- ## 數獨 ---- * 遇到一個空格就枚舉所有可能 * 若沒有合法的數字就回到上一個空格 ---- ```cpp= #include<bits/stdc++.h> using namespace std; bool chkR[9][10], chkC[9][10], chkB[9][10]; vector<int> g(81); void dfs(int i) { if (i == 81) { for (int j = 0; j < 81; j++) cout << g[j]; cout << '\n', exit(0); } else if (g[i] != 0) dfs(i + 1); else { for (int j = 1; j <= 9; j++) { int R = i / 9, C = i % 9, B = R / 3 * 3 + C / 3; if (!chkR[R][j] && !chkC[C][j] && !chkB[B][j]) { g[i] = j, chkR[R][j] = chkC[C][j] = chkB[B][j] = true; dfs(i + 1); g[i] = 0, chkR[R][j] = chkC[C][j] = chkB[B][j] = false; } } } } signed main() { ios_base::sync_with_stdio(false); cin.tie(0); string s; cin >> s; for (int i = 0; i < 81; i++) { if (s[i] == '.') g[i] = 0; else { g[i] = s[i] - '0'; int R = i / 9, C = i % 9, B = R / 3 * 3 + C / 3; if (chkR[R][g[i]] || chkC[C][g[i]] || chkB[B][g[i]]) cout << "No solution.\n", exit(0); chkR[R][g[i]] = chkC[C][g[i]] = chkB[B][g[i]] = true; } } dfs(0); cout << "No solution.\n"; return 0; } ``` --- ## 八皇后問題 ---- * 對每一列枚舉放皇后的位置 * 若所有位置皆不合法則回到上一列 ---- ```cpp= #include<bits/stdc++.h> using namespace std; bool chkC[11], chkD[21], chkE[21]; int N, g[11], ans; void dfs(int R) { if (R == N) { for (int i = 0; i < N; i++, cout << '\n') for (int j = 0; j < N; j++) if (g[i] == j) cout << 'Q'; else cout << 'x'; cout << '\n', ans++; } else { for (int C = 0; C < N; C++) { int D = R + C, E = R - C + (N - 1); if (!chkC[C] && !chkD[D] && !chkE[E]) { g[R] = C, chkC[C] = chkD[D] = chkE[E] = true; dfs(R + 1); g[R] = -1, chkC[C] = chkD[D] = chkE[E] = false; } } } } signed main() { ios_base::sync_with_stdio(false); cin.tie(0); cin >> N; dfs(0); cout << ans << "\n\n"; return 0; } ``` --- ## 背包問題 ---- 有 $n\ (1 \leq n \leq 20)$ 樣物品, 每個物品有自己的價值和重量 $(1 \leq p_i, w_i \leq 10^9)$ 現在有一個耐重 $k\ (1 \leq k \leq 10^9)$ 的背包, 問在所有物品只能選擇全放進背包或全不放進背包的情況下, 背包內的物品總價值最高是多少? ---- * 枚舉物品的子集合 * 檢查子集合總重是否超過 $k$ 並更新最高價格 ---- ```cpp= #include<bits/stdc++.h> using namespace std; signed main() { ios_base::sync_with_stdio(false); cin.tie(0); int n, k, p[20], w[20]; cin >> n >> k; for (int i = 0; i < n; i++) cin >> p[i] >> w[i]; int ttl = (1 << n); long long ans = 0; for (int i = 0; i < ttl; i++) { int t = i; long long sumP = 0, sumW = 0 for (int j = 0; j < n; j++, t /= 2) if (t % 2) sumP += p[j], sumW += w[j]; if (sumW <= k) ans = max(ans, sumP); } return 0; } ``` --- ## Next Permutation ---- ```cpp= bool my_next_permutation(vector<int> &num) { int n = num.size(); if(n == 1) return false; for(int i = n - 2, j = n - 1; i >= 0; i--, j--) if(num[i] < num[j]) { int k = n - 1; while(num[i] >= num[k]) k--; swap(num[i], num[k]); reverse(num.begin() + j, num.end()); return true; } return false; } ``` ---- ```cpp= next_permutation(v.begin(), v.end()); // 將v變成下一個排列 ``` ```cpp= prev_permutation(v.begin(), v.end()); // 將v變成前一個排列 ``` --- ## Lotto ### UVa 441, ZJ c074 ---- * 枚舉大小為6的子集合 * 將use陣列內最後6個值設為1 * 以next_permutation遍歷所有大小為6的子集合 ---- ```cpp= #include<bits/stdc++.h> #define int long long using namespace std; signed main() { ios_base::sync_with_stdio(false); cin.tie(0); bool fir = true; int n; while (cin >> n) { if (!n) return 0; if (fir) fir = false; else cout << '\n'; vector<int> v(n); for (int i = 0; i < n; i++) cin >> v[i]; vector<bool> use(n); for (int i = 0; i < 6; i++) use[i] = true; do { int cnt = 0; for (int i = 0; i < n; i++) if (use[i]) cout << v[i] << " \n"[cnt++ == 5]; } while (prev_permutation(use.begin(), use.end())); } return 0; } ```
{"metaMigratedAt":"2023-06-15T11:45:34.744Z","metaMigratedFrom":"Content","title":"枚舉","breaks":true,"contributors":"[{\"id\":\"6b95215f-91a7-4eaf-bcfe-d43740108f96\",\"add\":10584,\"del\":4762}]"}
    475 views