NC23486 小A与小B

小A与小B (nowcoder.com)

493dfe133bb24aa1b88cce0814f933e3.png
 

示例1

输入

4 5
. . . . .
. # # # .
. . . # D
. . C # .

输出

YES
3

备注:

1<=n,m<=1000

能够想到是让两人同时bfs搜索,但是实际写的时候 在很多地方出了错

1.B的走要分两次来走,不能一次直接走到最远的可达处,就是一次走两步,因为这样可能会跳过‘#’,从而出错;

2.每走一步都要把上次的“起点”全部走完,得到的新起点用于下一步的行动,所以这两种点“这一次的起点”,“下一次的起点”要分开存,不能混到一起,这里我是开了一个新的暂存对列,让其分别存每个人这一步的起点,然后让下一次的起点存放到q1和q2中,再下一步开始时,再先后把q1,q2中的点存放到q3中,因为A和B是分开走的,每个人走完后q3都会被清空,所以用一个q3分别存储就够了

下面是代码:

#include<bits/stdc++.h>
#include<queue>
#define endl '\n'
using namespace std;
typedef pair<int,int> PII;
const int N = 1001;
int n , m;
char g[N][N];
bool st[N][N][2];//如果1带你2同时为true,说明两人互相找到
int sx1,sy1,sx2,sy2;
int dx1[]={0,0,1,-1,1,1,-1,-1},dy1[]={1,-1,0,0,1,-1,-1,1};//A
int dx2[]={0,0,1,-1,0},dy2[]={1,-1,0,0,0};//B
int bfs(){//两人同时bfs
    int time=0;
    queue<PII> q1;//存放终点
    queue<PII> q2;//存放终点
    queue<PII> q3;//暂存队列,存放起点
    q1.push({sx1,sy1});
    q2.push({sx2,sy2});
    st[sx1][sy1][0] = st[sx2][sy2][1] = true;
    if(sx1==sx2&&sy1==sy2) return time;//特判,起点相同

    while(q1.size()||q2.size()){
        time++;
        while(q1.size()){
            q3.push(q1.front());//存放上一次的要走点
            q1.pop();
        }
        while(q3.size()){
            auto t1 =q3.front();
            int x1 = t1.first , y1 = t1.second;
            q3.pop();
            st[x1][y1][0] = true;
            for(int i=0;i<8;i++){//让A先走
                int nx1 = x1 +dx1[i],ny1 = y1 + dy1[i];
                if(nx1 >= 1 && ny1 >= 1 && nx1 <= n && ny1 <= m && !st[nx1][ny1][0] && g[nx1][ny1] != '#'){
                    st[nx1][ny1][0] = true ;
                    if(st[nx1][ny1][1]) return time;
                    q1.push({nx1,ny1});//存放下一次要走的
//                     cout<<nx1<<" "<<ny1<<endl;
                }                                                                      
            }
        }
        while(q2.size()){
            q3.push(q2.front());//存放上一次的要走点
            q2.pop();
        }
        while(q3.size()){
            auto t2 =q3.front(); 
            int x2 = t2.first , y2 = t2.second;
            q3.pop();
            for(int i=0;i<4;i++){//再让B走第一步
                int nx2 = x2 +dx2[i],ny2 = y2 + dy2[i];
                if(nx2 >= 1 && ny2 >= 1 && nx2 <= n && ny2 <= m && !st[nx2][ny2][1] && g[nx2][ny2] != '#'){
                    st[nx2][ny2][1] = true ;
                    if(st[nx2][ny2][0]) return time;
                    for(int j= 0; j < 4 ; j ++){
                        int nnx2 = nx2 +dx2[j],nny2 = ny2 + dy2[j];
                        if(nnx2 >= 1 && nny2 >= 1 && nnx2 <= n && nny2 <= m && !st[nnx2][nny2][1] && g[nnx2][nny2] != '#'){
                            st[nnx2][nny2][1] = true ;
                            if(st[nnx2][nny2][0]) return time;
                            q2.push({nnx2,nny2});
                        }
                    }

                }
            }
        }
        
    }
    return -1; 
}

int main(){
    cin>>n>>m;
    for(int i =1 ; i <= n ; i ++){
        for(int j =1 ; j <= m ; j ++){
            
            cin>>g[i][j];
            if(g[i][j]=='C') sx1=i,sy1=j;
            if(g[i][j]=='D') sx2=i,sy2=j;
        }
    }
    int ans =bfs();
    if(ans==-1) cout<<"NO"<<endl;
    else{
        cout<<"YES"<<endl;
        cout<<ans<<endl;
    }
//   cout<<st[4][4][0]<<" "<<st[3][5][1];
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鴎羽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值