1 条题解
-
0
自动搬运
来自洛谷,原作者为

Leasier
我们所知的是沧海一粟,我们所不知的是汪洋大海。搬运于
2025-08-24 22:25:15,当前版本为作者最后更新于2023-07-10 19:13:08,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
我们可以将题意及限制抽象成:
- 第 个人依次选择 中卡牌(分别去掉三张 中的卡牌后)的 张。
- 第 个人的选择固定。
- 每个人有一些必须选的,有一些卡牌集至少选一张的,还有一些必须不选的。
- 求去掉的三张卡牌依次可能是啥,或报告多解。
直接状压爆搜每个人的选择即可,但这样时间复杂度理论上是不对的,如果想要对可以一个一个人爆搜后 FWT 起来。
代码:
#include <iostream> #include <vector> using namespace std; int known = 0; int cnt[57], bans[7]; char s[17], guess[57][7], result[57][7]; bool no[27], ok1[7], ok2[17], ok3[27]; vector<int> v[7]; bool dfs0(int cur, int pre, int state, int ban){ if (cur == 19){ int size = v[0].size(); for (int i = 0; i < size; i++){ if ((state & v[0][i]) == 0) return false; } return true; } int cur_i = cur + 1; for (int i = pre + 1; i <= 21; i++){ if (!(state >> (i - 1) & 1) && !(ban >> (i - 1) & 1) && !(bans[0] >> (i - 1) & 1) && dfs0(cur_i, i, state | (1 << (i - 1)), ban)) return true; } return false; } bool dfs3(int cur, int pre, int state, int ban){ if (cur == 15){ int size = v[3].size(); for (int i = 0; i < size; i++){ if ((state & v[3][i]) == 0) return false; } return dfs0(15, 0, 0, ban | state); } int cur_i = cur + 1; for (int i = pre + 1; i <= 21; i++){ if (!(state >> (i - 1) & 1) && !(ban >> (i - 1) & 1) && !(bans[3] >> (i - 1) & 1) && dfs3(cur_i, i, state | (1 << (i - 1)), ban)) return true; } return false; } bool dfs2(int cur, int pre, int state, int ban){ if (cur == 11){ int size = v[2].size(); for (int i = 0; i < size; i++){ if ((state & v[2][i]) == 0) return false; } return dfs3(11, 0, 0, ban | state); } int cur_i = cur + 1; for (int i = pre + 1; i <= 21; i++){ if (!(state >> (i - 1) & 1) && !(ban >> (i - 1) & 1) && !(bans[2] >> (i - 1) & 1) && dfs2(cur_i, i, state | (1 << (i - 1)), ban)) return true; } return false; } inline bool check(int x, int y, int z){ int ban = (1 << (x - 1)) | (1 << (y - 1)) | (1 << (z - 1)); if (no[x] || no[y] || no[z] || (known & ban) != 0) return false; return dfs2(6, 0, 0, ban | known); } int main(){ int n; char ans1 = '\0', ans2 = '\0', ans3 = '\0'; cin >> n; cin.getline(&s[1], 2, '\n'); cin.getline(&s[1], 11, '\n'); for (int i = 1; i <= 5; i++){ int ch = s[i * 2 - 1] - 'A' + 1; known |= 1 << (ch - 1); no[ch] = true; } for (int i = 1; i <= n; i++){ cin.getline(&s[1], 13, '\n'); for (int j = 1; j <= 3; j++){ guess[i][j] = s[j * 2 - 1]; } do { cnt[i]++; result[i][cnt[i]] = s[cnt[i] * 2 + 5]; if (cnt[i] == 3) break; } while (result[i][cnt[i]] == '-'); } for (int i = 1; i <= n; i++){ int state = 0; for (int j = 1; j <= 3; j++){ state |= 1 << (guess[i][j] - 'A'); } for (int j = 1; j <= cnt[i] && result[i][j] == '-'; j++){ bans[(i + j) % 4] |= state; } if (result[i][cnt[i]] != '-'){ if (i % 4 == 1){ int ch = result[i][cnt[i]] - 'A' + 1; no[ch] = true; v[(i + cnt[i]) % 4].push_back(1 << (ch - 1)); } else { v[(i + cnt[i]) % 4].push_back(state); } } } for (int i = 1; i <= 6; i++){ for (int j = 7; j <= 12; j++){ for (int k = 13; k <= 21; k++){ if (check(i, j, k)) ok1[i] = ok2[j] = ok3[k] = true; } } } for (int i = 1; i <= 6; i++){ if (ok1[i]){ if (ans1 == '\0'){ ans1 = i + 'A' - 1; } else { ans1 = '?'; break; } } } for (int i = 7; i <= 12; i++){ if (ok2[i]){ if (ans2 == '\0'){ ans2 = i + 'A' - 1; } else { ans2 = '?'; break; } } } for (int i = 13; i <= 21; i++){ if (ok3[i]){ if (ans3 == '\0'){ ans3 = i + 'A' - 1; } else { ans3 = '?'; break; } } } cout << ans1 << ans2 << ans3; return 0; }
- 1
信息
- ID
- 6078
- 时间
- 4000ms
- 内存
- 512MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者