https://ac.nowcoder.com/acm/problem/23486
题意:
有一迷宫,小A每秒移动1次,方向为上下左右左上左下右上右下8个方向,小B每秒移动2次,方向为上下左右四个方向,问他们最早什么时候能够相遇?
分析:
迷宫问题,求最短相遇时间,优先考虑用bfs。因为小B每秒运动2次,所以我们可以给他每秒进行两次bfs,注意一下,bfs里面要判断一下是A还是B,小A是8个方向的,小B是4个方向的,用vis[0][x][y]和vis[1][x][y]分别记录走过的路径。
bfs:当小A走的时候,广搜周围路径,如果该点被小B所走过的时候,说明他们相遇了,答案出来了。
代码:
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<math.h>
#include<queue>
#include<iostream>
using namespace std;
typedef long long ll;
int i,j,n,k,m,t,s,y;
int ans,flag=1;
struct Hi{
int x,y;
};
queue<Hi>q1,q2;//小B。小A
char a[1005][1005];
int vis[2][1005][1005];//0代表小B,1代表小A
int xx[]={0,0,1,-1,1,1,-1,-1},yy[]={1,-1,0,0,1,-1,1,-1};
bool bfs(int k){//0代表小A,1代表小B
int t;
if(k==1){//小B
t=q1.size();
while(t--){
Hi f=q1.front();
vis[0][f.x][f.y]=1;
q1.pop();
for(int i=0;i<4;i++){
int dx=xx[i]+f.x;
int dy=yy[i]+f.y;
if(dx<0||dx>=n||dy<0||dy>=m||a[dx][dy]=='#'||vis[0][dx][dy]) continue;//此路不通
if(vis[1][dx][dy]) return flag=1;//找到对方了
vis[0][dx][dy]=1;//标记走过
q1.push((Hi){dx,dy});
}
}
return 0;//没碰到对方
}else{//把上面复制下来改一下就行了
t=q2.size();
while(t--){
Hi f=q2.front();
vis[1][f.x][f.y]=1;
q2.pop();
for(int i=0;i<8;i++){
int dx=xx[i]+f.x;
int dy=yy[i]+f.y;
if(dx<0||dx>=n||dy<0||dy>=m||a[dx][dy]=='#'||vis[1][dx][dy]) continue;//此路不通
if(vis[0][dx][dy]) return flag=1;//找到对方了
vis[1][dx][dy]=1;//标记走过
q2.push((Hi){dx,dy});
}
}
return 0;//没碰到对方
}
}
int main()
{
scanf("%d%d",&n,&m);
getchar();
for(i=0;i<n;i++){
for(j=0;j<m;j++){
cin>>a[i][j];
if(a[i][j]=='C'){
q2.push((Hi){i,j});
vis[1][i][j]=1;
}
else if(a[i][j]=='D'){
q1.push((Hi){i,j});
vis[0][i][j]=1;
}
}
}
while(!q1.empty() || !q2.empty()){
ans++;
if(bfs(0)) break;
if(bfs(1)) break;//找到了
if(bfs(1)) break;//小B一秒走2次
}
if(flag){
printf("YES\n");
printf("%d",ans);
}else{
printf("NO\n");
}
}
京公网安备 11010502036488号