FZU 2196 基础搜索 BFS 八

本文介绍了一道编程题FZU 2196的解题思路,利用带有岩浆蔓延特性的广度优先搜索(BFS)算法解决迷宫中人物逃离的问题。文章详细解释了如何实现人与岩浆交替移动的BFS过程,并特别指出在实现过程中需要注意的一个细节:判断人物行动点在等待期间是否被岩浆覆盖。

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

 

FZU  2196 :http://acm.fzu.edu.cn/problem.php?pid=2196

题意: 给出一个起点,终点,墙壁,通路,岩浆

           人先走,上下左右一次移动一格。

          岩浆后走,每次向上下左右蔓延周围各一格。

         问,人能否到达终点

 

一眼看出,附带岩浆的BFS。

 

思路:先将人装入队列,再将岩浆装入队列。

           便具有了,一个队列,但是具有人先走岩浆后走的特性。

           队列里装入的是点的位置以及,是岩浆还是人的区分变量sex。

          每一次根据取出元素是人还是岩浆的不用进行不同的BFS标记操作。

          book为标记数组。通路为-1,岩浆为0,墙壁也为0,人走过的点为1。则人能走的条件是,此点为-1,岩浆蔓延的条件是此点不为0(为了可以蔓延走过的1点)。

 

注意点:  交了一发没有过,有一个细节要注意:    

         假设有一个位置点X, 此点无岩浆,无人走过,所以标记为1入队。 但是之后的岩浆可能把这个位置给淹没了!! 这种情况,理论上就不能对这个点进行拓展了。

         所以对每一个人放入的可走点,要加入一个判断,此点是否在放在队列等待的时间内,被岩浆覆盖了。

 

上BFS代码:

 

#include"cstdio"
#include"cstring"
#include"queue"
#include"iostream"
#include"algorithm"
using namespace std;
#define inf 1009
#define loop(x,y,z) for(x=y;x<z;x++)

int T,n,m,sx,sy,gx,gy;
char pos[inf][inf];
int book[inf][inf];
int change[4][2]={0,1,0,-1,-1,0,1,0};
struct point                                  //存放了入队点信息,行、列、以及人走的点为1,岩浆走的点为0
{
    int x,y;
    int sex;
    point(int i,int j,int k)
    {
        x=i;y=j;sex=k;
    }
};
queue<point>q;

void init()                                   //初始化函数
{
    memset(book,-1,sizeof book);
    while(!q.empty())q.pop();
}
 
int pan(int i,int j)                            //判断有无越界函数
{
    if(i<0||i>=n||j<0||j>=m)return 0;
    return 1;
}

void bfs()
{
    int i,j;
    loop(i,0,n)
        loop(j,0,m)
            if(pos[i][j]=='S')                     //起点入队标记,记录终点位置
            {
                q.push(point(i,j,1));
                book[i][j]=1;
            }
            else if(pos[i][j]=='E')
            {
                gx=i;gy=j;
            }
    loop(i,0,n)                                    //岩浆入队标记
        loop(j,0,m)
            if(pos[i][j]=='!')
            {
                q.push(point(i,j,0));
                book[i][j]=0;
            }
            else if(pos[i][j]=='#')
                book[i][j]=0;
    while(!q.empty())
    {
        point t=q.front();
        q.pop();
        int sex=t.sex;
        if(sex)                                           //如果是人走的点
        {
            if(book[t.x][t.y]==0)continue;               //如果这个点在队列等待时间里被岩浆淹没了,就不进行拓展了
            loop(i,0,4)
            {
                int nowx=t.x+change[i][0];
                int nowy=t.y+change[i][1];
                if(pan(nowx,nowy)&&book[nowx][nowy]==-1)    //合法点标记入队
                {
                    book[nowx][nowy]=1;
                    q.push(point(nowx,nowy,1));
                    if(book[gx][gy]==1)                  //若终点拓展成功,输出Yes
                    {
                        printf("Yes\n");return;
                    }
                }
            }
        }
        else                                            //如果是岩浆走的点
        {
            loop(i,0,4)
            {
                int nowx=t.x+change[i][0];
                int nowy=t.y+change[i][1];
                if(pan(nowx,nowy)&&book[nowx][nowy]!=0)     //只需要标记并入队就好
                {
                    book[nowx][nowy]=0;
                    q.push(point(nowx,nowy,0));
                }
            }
        }
    }
    printf("No\n");
}

int main()
{
    int i;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        init();
        loop(i,0,n)
        scanf("%s",pos[i]);
        bfs();
    }
    return 0;
}

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值