【2022牛客多校第六场 Z题 Game on grid】dp

题目描述

在这里插入图片描述

输入描述

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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

宇智波一打七~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值