UVALive - 6469(博弈、记忆化搜索)
题意: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 */