[dp]Z-Game on grid 2022牛客多校第6场 M

题目描述

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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值