ABC349

1|0E

E - Weighted Tic-Tac-Toe (atcoder.jp)

这可不是博弈论!

推了半天性质,脑子要干爆了,发现这题固定的 3×3 棋盘,可以爆搜啊。

直接用搜索模拟所有过程即可,难点在优雅地实现。

int a[9]; int dp[512][512];//记忆化 inline bool check(int X) { for (int i = 0; i <= 6; i += 3) { if ((X & (1 << i)) and (X & (1 << i + 1)) and (X & (1 << i + 2))) {//横排三连 return true; } } for (int i = 0; i < 3; ++i) { if ((X & 1 << i) and (X & (1 << i + 3)) and (X & (1 << i + 6))) {//竖排三连 return true; } } if ((X & 1) and (X & 16) and (X & 256)) {//斜三连 return true; } if ((X & 4) and (X & 16) and (X & 64)) { return true; } return false; } bool dfs(int S, int T) {//S表示先手下过状态,T表示后手,用二进制位存储,定义先手赢为true if (check(S)) {//说明先手赢了 return true; } if (check(T)) { return false; } if (__builtin_popcount(S) + __builtin_popcount(T) == 9) {//已经走完所有格仍未决出胜负,计算谁分数高 i64 tot{};//分数 for (int i = 0; i < 9; i++) {//统计当前分数 if (S & (1 << i)) { tot += a[i]; } else { tot -= a[i]; } } return tot > 0; } if (dp[S][T] != -1) {return dp[S][T];} if (__builtin_popcount(S) == __builtin_popcount(T)) {//目前两人步数一样,轮到S先手下 for (int i = 0; i < 9; i++) { if ((S & (1 << i)) or (T & (1 << i))) {continue ;}//被下过了 if (dfs(S | (1 << i), T)) {//S有情况能赢 return dp[S][T] = 1; } } return dp[S][T] = 0; } else {//目前两人步数不一样,轮到T后手下 for (int i = 0; i < 9; ++i) { if ((S & (1 << i)) or (T & (1 << i))) { continue; } if (not dfs(S, T | (1 << i))) {//T有情况能赢 return dp[S][T] = 0; } } return dp[S][T] = 1; } } signed main() { std::cin.tie(nullptr)->sync_with_stdio(false); for (auto& x : a) std::cin >> x; std::memset(dp, -1, sizeof dp); std::cout << (dfs(0, 0) ? "Takahashi" : "Aoki") << '\n'; return 0; }

__EOF__

本文作者Kdlyh
本文链接https://www.cnblogs.com/kdlyh/p/18133732.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   加固文明幻景  阅读(84)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下
点击右上角即可分享
微信分享提示