AT_abc326_d ABC Puzzle 题解
AT_abc326_d ABC Puzzle 题解
看题
事实上,即使在 \(N=5\) 的情况下,也只有 \(66240\) 个网格满足「每行/每列恰好包含一个 A
、B
和 C
」。——官方题解
其实看到这道题,就感觉是搜索,这很显然。
但是我们会发现,最最最 native 的搜索,是 \(4^{5\times5}=2^{50}\) 的。
感觉不大可过,但是似乎又不太大。
考虑到原题中的限制很多很多,所以可以考虑剪枝。
下面的思路与 官方题解 的类似。
分析
题目中的限制有:
- 每行和每列恰好包含一个
A
、一个B
和一个C
。 - 第 \(x\) 行最左边的字符是 \(R_x\)。
- 第 \(x\) 列最上面的字符是 \(C_x\)。
我们一条一条的看,可以怎么剪枝。
0x01
限制:每行和每列恰好包含一个 A
、一个 B
和一个 C
。
于是,我们可以按行搜索,即每次递归填入一整行的字符。
然后我们在搜索的过程中记录:\(\mathit{have}_{i,0/1/2}\) 表示第 \(i\) 列是否有 A
/B
/C
。
然后在填入每一行的字符时,我们限制只能填入一个 A
、一个 B
和一个 C
。
0x02
限制:每行的第一个字符一定是 \(R_x\)。
于是,我们可以枚举每个字符填入的位置。
我们枚举 \(i\) 表示 \(R_x\) 填入的位置,然后枚举 \(j,k\) 表示其余两个字母的位置。
注意到除了后面两个字符的位置 \(j,k\)(在符合其余限制的情况下)可以调换:
0x03
限制:每一列第一个字符一定是 \(C_x\)。
于是,我们可以记录一个 \(\mathit{cover}_i\) 表示此时第 \(i\) 列上方是否已经被其他字符覆盖。
当我们填入字符的时候,如果 \(\mathit{cover}_i=0\) 就需要判断这个字符是否等于 \(C_i\)。
代码
评测记录:https://atcoder.jp/contests/abc326/submissions/47081201
跑的嘎嘎快(
#include <bits/stdc++.h> using namespace std; #define rep(i, n) for (int i = 0; i < (n); ++i) using vi = vector<int>; using vvi = vector<vi>; using vb = vector<bool>; int n; string r, c; vvi ans; void print(vvi &x) { for (auto i : x) { for (auto j : i) j == -1 ? putchar('.') : putchar('A' + j); putchar('\n'); } } #define td(a, b, c, _a, _b, _c) (a) = (_a), (b) = (_b), (c) = (_c) void dfs(int x, vb iscover, vb have[3]) { if (x == n) { for (int sb = 0; sb < 3; ++sb) for (int t : have[sb]) if (!t) return; printf("Yes\n"); print(ans), exit(0); } int op1 = r[x], op2, op3; if (op1 == 'A') op2 = 'B', op3 = 'C'; else if (op1 == 'B') op2 = 'A', op3 = 'C'; else op2 = 'A', op3 = 'B'; int sb1 = op1 - 'A', sb2 = op2 - 'A', sb3 = op3 - 'A'; int t1, t2, t3; for (int i = 0; i < n - 2; ++i) { if (!iscover[i] && c[i] != op1) continue; if (have[sb1][i]) continue; for (int j = i + 1; j < n; ++j) { if (!iscover[j] && c[j] != op2) continue; if (have[sb2][j]) continue; for (int k = i + 1; k < n; ++k) { if (j == k) continue; if (!iscover[k] && c[k] != op3) continue; if (have[sb3][k]) continue; td(t1, t2, t3, iscover[i], iscover[j], iscover[k]); iscover[i] = iscover[j] = iscover[k] = 1; ans[x][i] = sb1, ans[x][j] = sb2, ans[x][k] = sb3; have[sb1][i] = have[sb2][j] = have[sb3][k] = 1; // fprintf(stderr, "= JOIN (%d, %c) (%d, %c) (%d, %c)\n", i, op1, j, op2, k, op3); dfs(x + 1, iscover, have); // fprintf(stderr, "= THROW (%d, %c) (%d, %c) (%d, %c)\n", i, op1, j, op2, k, op3); td(iscover[i], iscover[j], iscover[k], t1, t2, t3); ans[x][i] = -1, ans[x][j] = -1, ans[x][k] = -1; have[sb1][i] = have[sb2][j] = have[sb3][k] = 0; } } } } signed main() { ios::sync_with_stdio(false); cin.tie(nullptr); cin >> n >> r >> c; rep(_, n) ans.push_back(vi(n, -1)); vb x = vb(n); vb t[3] = {x, x, x}; dfs(0, x, t); printf("No\n"); return 0; }
本文来自博客园,作者:RainPPR,转载请注明原文链接:https://www.cnblogs.com/RainPPR/p/solution-at-abc326-d.html
如有侵权请联系我(或 2125773894@qq.com)删除。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!