题意:给一个九宫格涂边,每次涂的边长为1,如果涂的这条边可以组成p个边长为1的正方形,就加p分,现在Tom和Jerry已经走了若干步,问接下来若两人用最优策略,谁会赢。
思路:刚开始没仔细读题以为就是个简单的模拟。。。没想到是个博弈,但是博弈题我没怎么做过啊。。
首先要了解必胜态和必败态的概念,在一棵博弈树上,如果该步是叶子节点,那么根据条件分高的就获胜,是必胜态,反之就是必败态;如果不是叶子节点,那么如果该节点的子节点中有必败态,那么该节点就是必胜态,反之就是必败态(因为接下来一步是对手的回合,无论哪步对手都会赢的话那自己这一步肯定会输)。
所以问题就是判断当前这一步是必败态还是必胜态。
搜索时用dfs搜到叶子节点进行回溯,如果子节点是必胜态,就接着搜其他子节点,如果都是必胜态,那么该节点就是必败态;如果子节点有必败态,那么该节点一定是必胜态,直接回溯。
注意判断当前是谁的回合,这个节点的状态是谁的状态。
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
bool vis[20][20];
int Tom200, Jerry404;
int getpoints(int a, int b){
int ret = 0;
if(b - a > 1){
if(a % 4 != 1)
if(vis[a - 1][b - 1] && vis[a][a - 1] && vis[b][b - 1]) ret++;
if(a % 4 != 0)
if(vis[a + 1][b + 1] && vis[a][a + 1] && vis[b][b + 1]) ret++;
}
else {
if(a > 4)
if(vis[a - 4][b - 4] && vis[a][a - 4] && vis[b][b - 4]) ret++;
if(a < 13)
if(vis[a + 4][b + 4] && vis[a][a + 4] && vis[b][b + 4]) ret++;
}
return ret;
}
vector<pair<int, int> > vct;
bool dfs(int score, bool tomTurn){
bool done = false;
for(int i = 0; i < vct.size(); i++) {
if(!vis[vct[i].first][vct[i].second]){
done = true;
vis[vct[i].first][vct[i].second] = vis[vct[i].second][vct[i].first] = true;
int p = getpoints(vct[i].first, vct[i].second);
if(!tomTurn) p = -p;
bool win = !dfs(score + p, !tomTurn);
vis[vct[i].first][vct[i].second] = vis[vct[i].second][vct[i].first] = false;
if(win) return true;
}
}
if(!done) return score > 0;
return false;
}
main() {
int cnt = 0;
int t, n;
scanf("%d", &t);
for(int cas = 1; cas <= t; cas++) {
memset(vis, 0, sizeof vis);
vct.clear();
Tom200 = Jerry404 = 0;
scanf("%d", &n);
for(int i = 0; i < n; i++) {
int a, b;
scanf("%d %d", &a, &b);
vis[a][b] = vis[b][a] = true;
if(a > b){
a = a ^ b;
b = a ^ b;
a = a ^ b;
}
if(i % 2) Jerry404 += getpoints(a, b);
else Tom200 += getpoints(a, b);
}
for(int i = 1; i < 16; i++) if((i % 4) >= 1 && !vis[i][i + 1]) vct.push_back(make_pair(i, i + 1));
for(int i = 1; i <= 12; i++) if(!vis[i][i + 4]) vct.push_back(make_pair(i, i + 4));
printf("Case #%d: ", cas);
bool win;
if(n % 2) win = !dfs(Tom200 - Jerry404, false);
else win = dfs(Tom200 - Jerry404, true);
puts(win ? "Tom200" : "Jerry404");
}
}