题解 | #小喵觅食(BFS)#

小喵觅食

https://ac.nowcoder.com/acm/contest/46597/C

题意:给定二维字符矩阵,‘*’ 代表障碍且不能通过,‘.’代表空且可以通过,一人位于点(x1,y1),一猫位于点(x2,y2),当人走到与猫的曼哈顿距离小于r2时人停止走动,此时猫会向人走来。人的活动范围为r1,代表人不能走到与(x1,y1)曼哈顿距离大于r1的点上,注意:当且仅当人走到与(x2,y2)曼哈顿距离小于r2时猫才会向人走来,否则猫处于静止态。请你求出人想与猫汇合的话,人与猫走的步数之和最小是多少。如果无法汇合,请输出-1

思路:

首先,猫的移动范围不受限制,以猫为源点做全局的最短路(BFS)。将猫为源点的最短路记录在mp中

而后以人为源点,在r1和r2的限制条件下BFS出人能到的所有点并且标记出到这些点的最小步数。将人为源点的最短路记录在mp2中

值得注意的是,mp1和mp2初始化为无穷大,以便判断无解的情况。

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long 
const int N =1000+100;
int n,m;
char a[N][N];
bool vis[N][N];
int mp[N][N][2];
int r1,r2;
int dir[5][2]={{0,0},{1,0},{-1,0},{0,1},{0,-1}};
int sx,sy,ex,ey;
struct node
{
    int x,y,dis;
};
bool check(int x,int y)
{
    if(x>=1&&x<=n&&y>=1&&y<=m&&!vis[x][y]&&a[x][y]!='*')
        return true;
    return false;
}
void BFS(int xx,int yy,int falg)
{
    queue<node> q;
    q.push({xx,yy,0});
    while(!q.empty())
    {
        node now=q.front();
        q.pop();
        if(a[now.x][now.y]!='*')
            mp[now.x][now.y][falg]=min(mp[now.x][now.y][falg],now.dis);
        if(vis[now.x][now.y]) continue;
        vis[now.x][now.y]=1;
        if(falg==1&&abs(now.x-sx)+abs(now.y-sy)<=r2) continue;
        for(int i=1;i<=4;i++)
        {
            node nex={now.x+dir[i][0],now.y+dir[i][1],now.dis+1};
            if(check(nex.x,nex.y))
            {
                if(falg==1)
                {
                    if(abs(nex.x-ex)+abs(nex.y-ey)<=r1)
                        q.push(nex);
                }
                else
                    q.push(nex);
            }
        }
    }
}
signed main()
{
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    cin>>n>>m>>r1>>r2;
    memset(mp,1e9,sizeof(mp));
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            cin>>a[i][j];
            mp[i][j][0]=1e9;mp[i][j][1]=1e9;
            if(a[i][j]=='M')
                sx=i,sy=j;
            if(a[i][j]=='P')
                ex=i,ey=j;
        }
    }
    BFS(sx,sy,0);
    memset(vis,0,sizeof(vis));
    BFS(ex,ey,1);
    int minn=1e9;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(abs(i-sx)+abs(j-sy)>r2||a[i][j]=='*') continue;
            else minn=min(minn,mp[i][j][0]+mp[i][j][1]);
    if(minn==1e9) cout<<-1;
    else cout<<minn;
    return 0;
}


全部评论

相关推荐

不愿透露姓名的神秘牛友
11-20 19:57
已编辑
某大厂 golang工程师 23.0k*16.0, 2k房补,年终大概率能拿到
点赞 评论 收藏
分享
10-24 13:36
门头沟学院 Java
Zzzzoooo:更新:今天下午有hr联系我去不去客户端,拒了
点赞 评论 收藏
分享
某牛奶:一觉醒来全球程序员能力下降200%,小伙成功scanf惊呆在座个人。
点赞 评论 收藏
分享
Pandaileee:校友加油我现在也只有一个保底太难了
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务