题目描述
Alice and Bob are playing a game on an n×mn\times mn×m grid where each cell has either 'A', 'B' or '.' written on it. They take turns moving a chess piece on the grid and Alice moves first.
Initially the piece is on cell (1,1)(1,1)(1,1). In each player's turn, he or she can move the piece one cell right or one cell down. That is, if the piece is on cell (x,y)(x,y)(x,y) before the turn, the player can move it to (x+1,y)(x+1,y)(x+1,y) or (x,y+1)(x,y+1)(x,y+1), as long as it doesn't go beyond the grid.
At any time, if the piece is on a cell with 'A', Alice wins and the game ends. If the piece is on a cell with 'B', Bob wins and the game ends. If the piece reaches cell (n,m)(n,m)(n,m) without the game ending, then it is a draw.
Since Alice cannot decide what acts Bob will take, she would like to know if she can be in control of the situation. Given the grid they're playing on, can you tell her if she can always find a way to win, draw or lose the game no matter what acts Bob takes?
输入描述:
In the first line an integer T (1≤T≤50)T\space (1 \le T \le 50)T (1≤T≤50), representing the number of test cases. For each test case, the first line contains two integers N,M (1≤N,M≤500)N,M\space (1\le N,M \le 500)N,M (1≤N,M≤500), representing the grid's size. Each of the next NNN lines for the case contains MMM characters (either 'A', 'B' or '.'), describing the grid.
输出描述:
For each test case, output three words 'yes' or 'no' in one line, representing if Alice can find a way to win, draw or lose the game respectively (without quotes).
示例1
输入
2 3 3 ..B ..B BB. 1 3 ...
输出
no no yes no yes no
题意: 给出一张地图,Alice和Bob两人轮流操纵棋子移动,起点是(1, 1),终点时(n, m),每次棋子只能向右或者向下移动,当棋子走到‘A’时Alice获胜,走到‘B’时Bob获胜,走到(n, m)时为平局,分别输出Alice是否一定能走到‘A’,是否一定能走到(n, m),是否一定能走到‘B’。
分析: 状态比较难想,设dp[i][j][0]表示从(i, j)出发是否一定能走到'A',dp[i][j][1]表示从(i, j)出发是否一定能走到'B',dp[i][j][2]表示从(i, j)出发是否一定能走到(n, m),状态初始化就是‘A’格子上dp[i][j][0]为true,‘B’格子上dp[i][j][1]为true,如果终点上面没有字母那么dp[n][m][2]为true,状态转移就是倒序枚举数组,如果当前(i, j)是Alice在下棋,那么dp[i][j][k] = dp[i+1][j][k] || dp[i][j+1][k],这意味着只需要右侧或下侧有一个格子能走到相应位置那从当前位置也可以走到那里,如果当前(i, j)是Bob在下棋,Bob的选择是随机的,所以必须右侧和下侧均为true当前位置才能为true,也就是dp[i][j][k] = dp[i+1][j][k] && dp[i][j+1][k],上面的更新都应该在当前位置为‘.’时进行,因为‘A’和‘B’的位置已经更新完了。最后要记得边界位置需要特殊处理一下,代码中有体现。
具体代码如下:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <string>
using namespace std;
char mp[505][505];
bool dp[505][505][3];//dp[i][j][0]表示从(i, j)出发能否一定走到'A'
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int T;
cin >> T;
while(T--){
int n, m;
cin >> n >> m;
for(int i = 0; i <= n; i++)
for(int j = 0; j <= m; j++)
dp[i][j][0] = dp[i][j][1] = dp[i][j][2] = false;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++){
cin >> mp[i][j];
if(mp[i][j] == 'A') dp[i][j][0] = true;
if(mp[i][j] == 'B') dp[i][j][1] = true;
}
if(mp[n][m] == '.') dp[n][m][2] = true;
for(int i = n; i >= 1; i--)
for(int j = m; j >= 1; j--){
if(i == n && j == m) continue;
if(i == n){//边界位置处理
dp[n+1][j][0] = dp[n][j+1][0];
dp[n+1][j][1] = dp[n][j+1][1];
dp[n+1][j][2] = dp[n][j+1][2];
}
if(j == m){
dp[i][m+1][0] = dp[i+1][m][0];
dp[i][m+1][1] = dp[i+1][m][1];
dp[i][m+1][2] = dp[i+1][m][2];
}
if((i+j)&1){
if(mp[i][j] == '.'){
dp[i][j][0] = max(dp[i][j][0], dp[i+1][j][0]&&dp[i][j+1][0]);
dp[i][j][1] = max(dp[i][j][1], dp[i+1][j][1]&&dp[i][j+1][1]);
dp[i][j][2] = max(dp[i][j][2], dp[i+1][j][2]&&dp[i][j+1][2]);
}
}
else{
if(mp[i][j] == '.'){
dp[i][j][0] = max(dp[i][j][0], dp[i+1][j][0]||dp[i][j+1][0]);
dp[i][j][1] = max(dp[i][j][1], dp[i+1][j][1]||dp[i][j+1][1]);
dp[i][j][2] = max(dp[i][j][2], dp[i+1][j][2]||dp[i][j+1][2]);
}
}
}
if(dp[1][1][0]) cout << "yes ";
else cout << "no ";
if(dp[1][1][2]) cout << "yes ";
else cout << "no ";
if(dp[1][1][1]) cout << "yes\n";
else cout << "no\n";
}
return 0;
}