Tempter of the Bone II(BFS)

本文介绍了一种利用广度优先搜索(BFS)解决迷宫问题的方法,特别关注了角色携带炸弹炸墙以寻找最短路径的场景。通过状态记录与比较优化搜索过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

炸弹问题,题中加了一个小人拿到i个炸弹后去炸墙,一个炸弹能炸一面墙

一步所需时间为1秒,安炸弹到爆炸所需要一秒,也就是说从走到那面墙开始算起到通过那面墙所需要的时间为2秒

问多少秒后可以到达出口

如果出不去就输出-1


记录S点的坐标后开始BFS

由于有炸错墙的可能性,所以炸了墙之后不能在原图map中修改,需要有一个记录状态的数组 这里叫做state 在结构体里

state[i][j]表示在走到(i,j)的时候的炸弹数

一开始没走的时候初始化为-1吧是为了不跟没有炸弹时候的0混淆

遇到炸弹拿炸弹 遇到墙炸了它  如果是平路的话就要实时更新身上携带的炸弹数

然后用本次路径结束后所剩余的炸弹数跟上次路径结束后的炸弹数相比

如果比上次路径结束后的炸弹多的话就入队  意味着少用了炸弹也就是时间少了还有就是不需要炸那么多墙

然后实时更新本次状态

最重要是更新本次在(x1,y1)点时候身上的炸弹

然后就是判断哪条路径走的秒数少啦  在状态判断的时候其实也有一部分原因是为了判断最短路径

思路很清晰接下来贴代码  代码也有一部分注释

#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <cctype>
#include<algorithm>
#include<cmath>
#define INF 100000
using namespace std;
int N, M, ans, sx, sy;

char map[10][10];

int dir[4][2] = { 0, 1, 0, -1, 1, 0, -1, 0 };

struct Node
{
    int x, y, vs, step;
    int state[8][8];
    int  check( int x, int y )
    {
        if( x >= 0 && x < N && y >= 0 && y < M )
            return 1;
        return 0;
    }

} now;
int BFS( )
{
    memset( now.state, -1, sizeof( now.state ) ) ; //初始化状态到达每个点的炸弹为-1(为了和到达某个点时炸弹为0混淆)
    now.x = sx;
    now.y = sy;
    now.step= 0;
    now.vs = 0;//身上拥有的炸弹初始化为0
    now.state[sx][sy] = 0;//起点炸弹数为0
    queue<Node>q;
    q.push(now);
    while( !q.empty() )
    {
        Node temp = q.front();
        q.pop();
        if( ans != INF && temp.step >= ans )
            continue;
        for( int i = 0; i < 4; ++i )
        {
            int x1 = temp.x + dir[i][0];
            int y1 = temp.y + dir[i][1];
            int t1 = temp.step;
            int vs1 = -1;
            if(now.check(x1,y1))
            {
                if( map[x1][y1] == 'D' )//找到终点
                {
                    ans = min(ans,t1+1);//寻找最优路线(步数最少)
                    continue;
                }
                else if( temp.state[x1][y1] > -1 || map[x1][y1] == '.' ) // 该点已经走过

                {
                    t1 += 1;
                    vs1 = temp.vs;//实时更新身上携带的炸弹数
                }
                else if( map[x1][y1] == 'X' && temp.vs > 0 )//遇到墙而且身上有炸弹
                {
                    t1 += 2;//走上前引爆墙总共需要2秒
                    vs1 = temp.vs - 1;//引爆一个炸弹
                }
                else if( isdigit( map[x1][y1] ) )//遇到炸弹
                {
                    t1 += 1;//走一步拿炸弹
                    vs1 = temp.vs + ( map[x1][y1] - '0' );//拿炸弹
                }


                if( vs1 > temp.state[x1][y1] )//本次携带的炸弹数量多于上次在(x1,y1)坐标时的炸弹数量
                {
                    now.x = x1, now.y = y1, now.step = t1;
                    now.vs = vs1;
                    memcpy( now.state, temp.state, sizeof( now.state ) );//状态更新
                    now.state[x1][y1] = vs1;
                    q.push(now);//now 为最优  入队
                }
            }
        }
    }
    if( ans == INF )
        return 0;
    else
        return 1;
}


int main()
{
    while( scanf( "%d %d", &N, &M ), N | M )
    {
        for( int i = 0; i < N; ++i )
        {
            scanf( "%s", map[i] );
            for( int j = 0; j < M; ++j )
            {
                if( map[i][j] == 'S' )
                    sx = i, sy = j;
            }
        }
        ans = INF;
        if(BFS())
        {
            printf("%d\n",ans);
        }
        else printf("-1\n");
        // printf( BFS() ? "%d\n" : "-1\n", ans );

    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值