FZU 2196 基础搜索 BFS 八

 

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;xq;

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;
}

 

 

 

 

 

你可能感兴趣的:(搜索)