题意:q,p, r分别代表最底下一行,中间一行和最上面一行的格子数
A、B两人拿格子,每次选中一个格子,则它的上面及右边的格子全部被拿走
谁拿到(1,1)这个格子算输
A先拿,问A是否能赢,若能赢则输出拿的第一个格子的位置
思路:记忆化搜索,如果最后遇到 r == 0 &&p==0&&q==1则说明该情况一定输,那么它的上一种情况一定是赢的
所以枚举p,q,r即可
代码如下:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll INF = 1e14 + 7;
const int N = 110;
int n, m;
int dp[N][N][N], col[N][N][N], row[N][N][N];
int dfs(int r, int q, int p)
{
if(r == 0 && q == 0 && p == 1) return dp[r][q][p] = -1;
if(dp[r][q][p]) return dp[r][q][p];
for(int i = r - 1; i >= 0; i--)
{
if(dfs(i, q, p) == -1)
{
col[r][q][p] = i + 1;
row[r][q][p] = 3;
return dp[r][q][p] = 1;
}
}
for(int i = q - 1; i >= 0; i--)
{
if(dfs(min(r, i), i, p) == -1)
{
col[r][q][p] = i + 1;
row[r][q][p] = 2;
return dp[r][q][p] = 1;
}
}
for(int i = p - 1; i >= 1; i--)
{
if(dfs(min(r, i), min(q, i), i) == -1)
{
col[r][q][p] = i + 1;
row[r][q][p] = 1;
return dp[r][q][p] = 1;
}
}
return dp[r][q][p] = -1;
}
int main()
{
int t, cas, p, q, r;
scanf("%d", &t);
memset(dp, 0, sizeof(dp));
while(t--)
{
scanf("%d%d%d%d", &cas, &p, &q, &r);
if(dfs(r, q, p) == -1)
{
printf("%d L\n", cas);
}
else
{
printf("%d W %d %d\n", cas, col[r][q][p], row[r][q][p]);
}
}
return 0;
}
/*
4
1 3 3 3
2 3 1 0
3 3 2 0
4 97 64 35
*/