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