题目描述

小A与小B这次两个人都被困在了迷宫里面的两个不同的位置,而他们希望能够迅速找到对方,然后再考虑如何逃离迷宫的事情。小A每次可以移动一个位置,而小B每次可以移动两次位置,小A移动的方向是上下左右左上左下右上右下8个方向,小B移动的方向是上下左右4个方向,请问他们最早什么时候能够找到对方,如果他们最终无法相遇,那么就输出”NO"。

输入描述:
第一行两个整数N,M分别表示迷宫的行和列。\
接下来一个N\times M 的矩阵\其中"C"表示小A的位置,"D"表示小B的的位置,\
"#"表示不可通过的障碍,"."则是可以正常通过的位置。\字符用空格隔开\第一行两个整数N,M分别表示迷宫的行和列。
接下来一个N×M的矩阵
其中"C"表示小A的位置,"D"表示小B的的位置,
"#"表示不可通过的障碍,"."则是可以正常通过的位置。
字符用空格隔开

输出描述:
如果可以相遇,第一行输出一个YES,第二行一个整数输出最短的相遇时间。
否则就输出一个NO表示不能相遇。

示例1

输入
4 5
. . . . .
. # # # .
. . . # D
. . C # .

输出
YES
3

小A和小B被困在迷宫里,两人都可以移动且小A可以向上下左右左上左下右上右下移动,小B移动的方向是上下左右4个方向移动两次,显然这个一个双向bfs问题,跑两遍bfs即可,但是小b移动两次需要特殊处理一下。

该题的要点有:
地图的读入有空格,需要getchar()
双向bfs
小b的移动需要特殊处理(见代码注释)

代码:

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1005;
int du[maxn];
vector<int> v[maxn],ve[maxn];
int n,m,l,r;
int dir[8][2]={{1,0},{0,1},{-1,0},{0,-1},{-1,-1},{1,1},{1,-1},{-1,1}} ;
int vis[2][maxn][maxn];
char mp[maxn][maxn];
struct node{
	int x,y;
};

queue<node> q,p;

void bfs1(){
	while(!q.empty()){
		node tmp=q.front();
		q.pop();
		for(int i=0;i<8;i++){
			int xx=tmp.x+dir[i][0];
			int yy=tmp.y+dir[i][1];
			if(xx<1||yy<1||xx>n||yy>m) continue;
			if(vis[0][xx][yy]==-1&&mp[xx][yy]!='#'){
				q.push(node{xx,yy});
				vis[0][xx][yy]=vis[0][tmp.x][tmp.y]+1;
			}
		}
	}
}

void bfs2(){
	while(!p.empty()){
		node tmp=p.front();
		p.pop();
		for(int i=0;i<4;i++){
			int xx=tmp.x+dir[i][0];
			int yy=tmp.y+dir[i][1];
			if(xx<1||yy<1||xx>n||yy>m) continue;
			if(vis[1][xx][yy]==-1&&mp[xx][yy]!='#'){
				p.push(node{xx,yy});
				vis[1][xx][yy]=vis[1][tmp.x][tmp.y]+1;
			}
		}
	}
}
int main(){
	cin>>n>>m;
	memset(vis,-1,sizeof vis);
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			getchar();
			mp[i][j]=getchar();
			if(mp[i][j]=='C'){
				vis[0][i][j]=0;
				q.push(node{i,j});
			}
			if(mp[i][j]=='D'){
				vis[1][i][j]=0;
				p.push(node{i,j});
			}
		}
	}
	
	bfs1();
	bfs2();
	

	int ans=0x3f3f3f3f;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			if(vis[0][i][j]!=-1&&vis[1][i][j]!=-1){
				int tmp=vis[1][i][j]/2+(vis[1][i][j]&1); //小b一次走两步,所以/2向上取整
				ans=min(ans,max(vis[0][i][j],tmp));
			}
		}
	}
	if(ans==0x3f3f3f3f)cout<<"NO"<<endl;
	else{
		cout<<"YES"<<endl;
		cout<<ans<<endl;
	}

    return 0;
}