小A和小B和幽灵追两人(双向BFS)

链接:https://ac.nowcoder.com/acm/contest/549/G
来源:牛客网

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

输入描述:

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

输出描述:

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

输入

复制
4 5
. . . . .
. # # # .
. . . # D
. . C # .

输出

复制
YES
3

备注:

1≤n,m≤1000

两个人走过的路径分别用
vis[0][maxn][maxn]
vis[1][maxn][maxn]
来标记。
小a走的时候
1.检查自己的地图(防止重复走一个地方)
2.检查小b的地图,看看小b是否走过这个地方(如果小b走过了,那就可以视为他们相遇了)
同理可得:
小b走的时候
1.检查自己的地图(防止重复走一个地方)
2.检查小a的地图,看看小a是否走过这个地方(如果小a走过了,那就可以视为他们相遇了)
基本思想就是:

我们标记小A和小B走过的地方,如果小B走到小A走过的/小A走到小B走过的地方,那么就直接输出当前时间
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
/*
这个题就是说,两个人能不能相遇,
第一个人一次移动一个位置,方向是上下左右左上左下右上右下8个方向
第二个人一次移动两个位置,方向是上下左右 
*/ 
const int maxn=1010;
int dx[8]={0,0,1,-1,1,1,-1,-1};
int dy[8]={1,-1,0,0,1,-1,1,-1};
bool vis[2][maxn][maxn];
char map[maxn][maxn];
int n,m; 
struct node{
    int x,y;
};
queue<node> q[2];
bool bfs(int x){
    int sz=q[x].size();
    while(sz--){//这里要注意
        node temp=q[x].front();
        q[x].pop();
        for(int i=0;i<8-4*x;i++){
            int nx=temp.x+dx[i],ny=temp.y+dy[i];
            if(nx<0||nx>=n||ny<0||ny>=m||map[nx][ny]=='#') continue;
            if(vis[1-x][nx][ny]) return true;
            if(!vis[x][nx][ny]){
                q[x].push(node{nx,ny});
                vis[x][nx][ny]=true;
            }
        }
    }
    return false; 
} 
int min_step(){
    int res=0;
    while(!q[0].empty()||!q[1].empty()){
        res++;
        if(bfs(0)) return res;
        if(bfs(1)) return res;
        if(bfs(1)) return res;
    }
    return -1;
}
int main(){
    cin>>n>>m;
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            cin>>map[i][j];
            if(map[i][j]=='C'){
                q[0].push(node{i,j});
                vis[0][i][j]=true;
            }
            else if(map[i][j]=='D'){
                q[1].push(node{i,j});
                vis[1][i][j]=true;
            }
        }
    }
    int ans=min_step();
    if(ans==-1){
        cout<<"NO"<<endl;
    }
    else{
        cout<<"YES"<<endl;
        cout<<ans<<endl;
    }
}

然后这个HDU3085和上面的差不多:

传送门

题目大意:给出一个迷宫,一个男孩和一个女孩还有两只鬼,男孩每秒钟走3格,女孩每秒钟走1格,鬼每秒钟向四周分裂2格,问男孩和女孩能否在鬼占领迷宫之前汇合,能的话输出汇合最短时间,否则输出-1

 这个和那个思路是一样的就是多了一个判断是否被鬼魂追到

#include<iostream>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std; 
const int maxn=1e3+100;
char map[maxn][maxn];
bool vis[2][maxn][maxn];
int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};
struct node{
    int x,y;
}g[2];
int k,step;
int n,m;
queue<node>q[2];
bool check(int x,int y)
{
    if(x<0||y<0||x>=n||y>=m)
        return false;
    if(map[x][y]=='X')
        return false;
    for(int i=0;i<2;i++)
        if(step*2>=abs(x-g[i].x)+abs(y-g[i].y))
            return false;
    return true;
}
int bfs(int x){    
    int sz=q[x].size();
    while(sz--){
        node temp=q[x].front();
        q[x].pop(); 
        if(!check(temp.x,temp.y)){
            continue;
        }
        for(int i=0;i<4;i++){
            int nx=temp.x+dx[i];
            int ny=temp.y+dy[i];
            if(!check(nx,ny)) continue;
            if(vis[1-x][nx][ny]){
                return true;
            }
            if(!vis[x][nx][ny]){
                q[x].push(node{nx,ny});
                vis[x][nx][ny]=true;
            }
        }
    }
    return false; 
}
int min_step(){ 
    step=0;
    while(!q[0].empty()||!q[1].empty()){
        step++;
        if(bfs(0)) return step;
        if(bfs(0)) return step;
        if(bfs(0)) return step;
        if(bfs(1)) return step; 
    }
    return -1;
}
int main(){
    int t;
    cin>>t;
    while(t--){
        memset(vis,false,sizeof(vis));
        while(!q[0].empty()) q[0].pop();
        while(!q[1].empty()) q[1].pop();
        cin>>n>>m;
        k=0;
        for(int i=0;i<n;i++){
            scanf("%s",map[i]);
        }
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(map[i][j]=='M'){
                    q[0].push(node{i,j});
                    vis[0][i][j]=true;
                }
                else if(map[i][j]=='G'){
                    q[1].push(node{i,j});
                    vis[1][i][j]=true;
                }
                else if(map[i][j]=='Z'){
                    g[k].x=i;
                    g[k].y=j;
                    k++;
                }
            }
        }    
        int ans=min_step();
        cout<<ans<<endl;
    }
} 

 

 令一种写法:传送门
posted @ 2021-01-26 22:59  lipu123  阅读(131)  评论(0编辑  收藏  举报