题意:
就是给出一个m * n的矩阵,然后Harry每次横切,Vicky每次纵切。
但是要求每次切的时候需要切除整数块,轮到谁没法切了,那就是他输了。
思路:
考虑博弈,设d[n][m][2]为长度为n * m的块谁能赢,0表示Harry先切,1表示Vicky先切。
当某一个人切完之后的任何一个状态都使得对方输那么这个人就赢了。
比赛的时候一直在考虑切完后每一块因为先手的人不同可能会导致结果不一样,其实写SG函数
还是要抓住定义,单单从下一步的所有方案中使得对方全部不能赢即可。
后记:
其实这题也不能用SG函数,每次分完之后的状态之间还是有关系,比如一个2 * 10的块
分成2 * 1跟2 * 9,后继一赢一输,实际上还是可以赢的。就是因为这两个状态之间还是存在关系。
所以这个代码糊了。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N = 2e5 + 10;
int d[510][510][2];//横纵
bool dfs(int n, int m, int cnt)
{
if (d[n][m][cnt] != -1)
return d[n][m][cnt];
bool ans = 0;
if (cnt == 1)
{
for (int i = 1; i < n; i++)
{
ans |= !(dfs(i, m, 0) || dfs(n - i, m, 0));
}
}
else
{
for (int i = 1; i < m; i++)
{
ans |= !(dfs(n, i, 1) || dfs(n, m - i, 1));
}
}
return d[n][m][cnt] = ans;
}
int main()
{
#ifdef LOCAL
freopen("E:/input.txt", "r", stdin);
#endif
int t;
cin >> t;
memset(d, -1, sizeof d);
d[1][1][0] = d[1][1][1] = 0;
while (t--)
{
int n, m;
string s;
cin >> n >> m >> s;
if (s == "Harry")
{
if (dfs(n, m, 0))
puts("Harry can win");
else
puts("Harry cannot win");
}
else
{
if (dfs(n, m, 1))
puts("Vicky can win");
else
puts("Vicky cannot win");
}
}
return 0;
}