B-迷宫

链接: https://www.nowcoder.net/acm/contest/68/B
来源:牛客网

题目描述

这是一个关于二维迷宫的题目。我们要从迷宫的起点 'S' 走到终点 'E',每一步我们只能选择上下左右四个方向中的一个前进一格。 'W' 代表墙壁,是不能进入的位置,除了墙壁以外的地方都可以走。迷宫内的 'D' 代表一道上锁的门,只有在持有钥匙的时候才能进入。而 'K' 则代表了钥匙,只要进入这一格,就会自动地拿到钥匙。最后 '.' 则是代表空无一物的地方,欢迎自在的游荡。

本题的迷宫中,起点、终点、门跟钥匙这四个特殊物件,每一个恰好会出现一次。而且,此迷宫的四周 (最上面的一行、最下面的一行、最左边的一列以及最右边的一列) 都会是墙壁。

请问,从起点到终点,最少要走几步呢?

输入描述:

输入的第一行有两个正整数H, W,分别代表迷宫的长跟宽。
接下来的H行代表迷宫,每行有一个长度恰为W的字串,此字串只包含`'S'`, `'E'`, `'W'`, `'D '`, `'K'`, `'.'`这几种字元。

输出描述:

请在一行中输出一个整数代表答案,如果无法从起点走到终点,请输出-1。

链接:https://www.nowcoder.net/acm/contest/68/B
来源:牛客网

示例1

输入

4 12
WWWWWWWWWWWW
WE.W.S..W.KW
W..D..W....W
WWWWWWWWWWWW

输出

20
示例2

输入

6 6
WWWWWW
WEWS.W
W.WK.W
W.WD.W
W.W..W
WWWWWW

输出

-1

题意:求S到E的最小步数,其中有门和钥匙的情况,分开bfs就可以了。

思路:分两种情况:首先不用门的直接S到E的最小步数,bfs求得ans1。然后需要门的时候,此时必然需要钥匙,先bfs求得S到K的最小步数ans2,然后以K为起点,bfs求得K到E的最小步数ans3,最后比较ans1和ans2+ans3的大小,输出最小的即可。都不存在则输出-1。

因本人太菜,写了3个bfs,其实都差不多,还请大神不要见怪。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
struct node
{
    ll x,y,s;
};
char mp[550][550];
ll n,m,sx,sy,kx,ky,vis[550][550];
ll mv[4][2]={-1,0,0,1,1,0,0,-1};
ll bfs_E()               //bfs求直接S到E
{
    memset(vis,0,sizeof(vis));
    node now;
    now.x=sx;
    now.y=sy;
    now.s=0;
    queue<node>q;
    q.push(now);
    vis[now.x][now.y]=1;
    while(!q.empty())
    {
        now=q.front();q.pop();
        for(ll i=0;i<4;i++)
        {
            ll X=now.x+mv[i][0];
            ll Y=now.y+mv[i][1];
            if(X>=1&&X<=n&&Y>=1&&Y<=m&&vis[X][Y]==0&&mp[X][Y]!='W'&&mp[X][Y]!='D')
            {
                vis[X][Y]=1;
                node nex;
                nex.x=X;
                nex.y=Y;
                nex.s=now.s+1;
                if(mp[nex.x][nex.y]=='E')return nex.s;
                q.push(nex);
            }
        }
    }
    return -1;
}
ll bfs_K()            //bfs求S到K
{
    memset(vis,0,sizeof(vis));
    node now;
    now.x=sx;
    now.y=sy;
    now.s=0;
    queue<node>q;
    q.push(now);
    vis[now.x][now.y]=1;
    while(!q.empty())
    {
        now=q.front();q.pop();
        for(ll i=0;i<4;i++)
        {
            ll X=now.x+mv[i][0];
            ll Y=now.y+mv[i][1];
            if(X>=1&&X<=n&&Y>=1&&Y<=m&&vis[X][Y]==0&&mp[X][Y]!='W'&&mp[X][Y]!='D')
            {
                vis[X][Y]=1;
                node nex;
                nex.x=X;
                nex.y=Y;
                nex.s=now.s+1;
                if(mp[nex.x][nex.y]=='K')
                {
                    kx=nex.x;
                    ky=nex.y;
                    return nex.s;
                }
                q.push(nex);
            }
        }
    }
    return -1;
}
ll bfs_K_E()          //bfs求K到E
{
    memset(vis,0,sizeof(vis));
    node now;
    now.x=kx;
    now.y=ky;
    now.s=0;
    queue<node>q;
    q.push(now);
    vis[now.x][now.y]=1;
    while(!q.empty())
    {
        now=q.front();q.pop();
        for(ll i=0;i<4;i++)
        {
            ll X=now.x+mv[i][0];
            ll Y=now.y+mv[i][1];
            if(X>=1&&X<=n&&Y>=1&&Y<=m&&vis[X][Y]==0&&mp[X][Y]!='W')
            {
                vis[X][Y]=1;
                node nex;
                nex.x=X;
                nex.y=Y;
                nex.s=now.s+1;
                if(mp[nex.x][nex.y]=='E')return nex.s;
                q.push(nex);
            }
        }
    }
    return -1;
}
int main()
{
    while(~scanf("%lld%lld",&n,&m))
    {
        for(ll i=1;i<=n;i++)
        {
            scanf("%s",mp[i]+1);
            for(ll j=1;j<=m;j++)
            {
                if(mp[i][j]=='S')
                {
                    sx=i;
                    sy=j;
                }
            }
        }
        ll ans1=-1,ans2=-1,ans3=-1;
        ans1=bfs_E();
        ans2=bfs_K();
        if(ans2!=-1)
        {
            ans3=bfs_K_E();
        }
        if(ans1==-1)
        {
            if(ans2==-1)printf("-1\n");
            else
            {
                if(ans3==-1)printf("-1\n");
                else printf("%lld\n",ans2+ans3);
            }
        }
        else
        {
            if(ans2==-1)printf("%lld\n",ans1);
            else
            {
                if(ans3==-1)printf("%lld\n",ans2);
                else printf("%lld\n",min(ans1,ans2+ans3));
            }
        }
    }
    return 0;
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值