题目描述
输入描述
2
3 3
…B
…B
BB.
1 3
…
输出描述
no no yes
no yes no
题意
有一个n*m的棋盘,Alice和Bob轮流进行操作,每操作一步都是从当前点到右边的点或下面的点,如果走到了标志为’A’的点就是Alice赢,如果走到了标志为’B’的点就是Bob赢,如果走到了不能再走的时候还没有决出胜负那就是平局,问Alice在不知道Bob怎么走的情况下能不能稳赢,稳平局,稳输
思路
这是一个dp,状态是三维,dp[i][j][k],k=0代表当前Alice能不能稳赢,k=1代表当前Alice能不能稳平局,k=2代表Alice能不能稳输,dp[i][j][k]表示的是从(i,j)到(n,m)能不能完成这三种状态,然后如果这一步是Alice走的话,也就是当前i+j是偶数,那么就代表是Alice先手,如果它的右边或下边有一个能成功的话那么就行,或者如果当前的位置是’A’的话也行,其他两个跟这个一样,下面看代码把:
#include<bits/stdc++.h>
using namespace std;
const int N = 510;
bool st[N][N];
char s[N][N];
struct node{
int x,y;
};
int n,m;
bool dp[N][N][3];
void solve(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%s",s[i]+1);
memset(dp,false,sizeof dp);
for(int i=n;i>=1;i--){
for(int j=m;j>=1;j--){
int t = i+j;
t &= 1;
if(!t){
if(s[i][j] == 'A'){
dp[i][j][0] = 1;
}
else if(s[i][j] == 'B'){
dp[i][j][2] = 1;
}
else if(s[i][j] == '.'){
if(i == n && j == m){
dp[i][j][1] = 1;
continue;
}
if(i < n){
dp[i][j][0] |= dp[i+1][j][0];
dp[i][j][1] |= dp[i+1][j][1];
dp[i][j][2] |= dp[i+1][j][2];
}
if(j < m){
dp[i][j][0] |= dp[i][j+1][0];
dp[i][j][1] |= dp[i][j+1][1];
dp[i][j][2] |= dp[i][j+1][2];
}
}
}
else{
if(s[i][j] == 'A'){
dp[i][j][0] = 1;
}
else if(s[i][j] == 'B'){
dp[i][j][2] = 1;
}
else if(s[i][j] == '.'){
if(i == n && j == m){
dp[i][j][1] = 1;
continue;
}
for(int k=0;k<3;k++) dp[i][j][k] = 1;
if(i < n){
dp[i][j][0] &= dp[i+1][j][0];
dp[i][j][1] &= dp[i+1][j][1];
dp[i][j][2] &= dp[i+1][j][2];
}
if(j < m){
dp[i][j][0] &= dp[i][j+1][0];
dp[i][j][1] &= dp[i][j+1][1];
dp[i][j][2] &= dp[i][j+1][2];
}
}
}
}
}
bool flag[3] = {dp[1][1][0],dp[1][1][1],dp[1][1][2]};
if(flag[0]) printf("yes ");
else printf("no ");
if(flag[1]) printf("yes ");
else printf("no ");
if(flag[2]) printf("yes\n");
else printf("no\n");
}
int main(){
int _;
scanf("%d",&_);
while(_--) solve();
return 0;
}