UVa 11624 Fire!(搜索 -- BFS)

这是一道关于使用BFS解决迷宫中人物逃生问题的编程题。题目要求考虑火势蔓延和人物移动,通过两次BFS分别模拟火势和逃生路径。需要注意火势蔓延至边界及多个起火点的情况,以及人物可以在非墙壁位置离开迷宫视为成功逃生。在实现过程中,因边界处理和初始条件设置不当导致了一些错误,提醒解题者必须注重细节和全面考虑问题。
摘要由CSDN通过智能技术生成

题目链接:点击打开链接

题目大意:有个人在迷宫工作,某天迷宫里的某些地方着火了,他要逃出去,问他是否能逃出去?只要从不是墙壁的地方走出迷宫范围就算逃出去,火向上下左右四个方向蔓延,蔓延速度跟人的速度一样

解题思路:先对火蔓延的情况BFS一次,再对人逃跑路线BFS一次。看起来好像很简单,但是有些细节要注意——如果人下一时刻要走到的地方火在下一时刻会蔓延到,那么人就不能往这里走;起火的地方可能不止一个;人可以从任意一个没有墙挡住的地方逃出迷宫(也就是走出迷宫边界就算成功逃离)。


由于考虑可以走出迷宫边界,输入的迷宫最好从1~r和1~c,结果用第一种方法做的时候这里没处理好折腾了一下午;做第二种方法的时候又因为没有把火烧到迷宫范围外的时间初始化为INF(因为火是不会蔓延到边界外的),又折腾了一晚上... 还不够细心,还要努力!


第一种方法(参考别的大神的解题思路,链接:点击打开链接

#include <cstring>
#include <algorithm>
#define MAXN 1005
using namespace std;

struct Point
{
    int x;
    int y;
    int step;
    bool fire;
};

Point fire[MAXN*MAXN],q[MAXN*MAXN],start;

char maze[MAXN][MAXN];
int vis[MAXN][MAXN];
int dx[]= {-1,0,0,1};
int dy[]= {0,-1,1,0};
int r,c;
int cnt;

bool inMap(int x,int y)
{
    if(x>0 && x<=r && y>0 && y<=c)
        return true;
    return false;
}

int bfs()
{
    int fnt=0,rear=0;
    for(int i=0; i<cnt; i++)
        q[rear++]=fire[i];
    q[rear++]=start;
    while(fnt<rear)
    {
        Point &temp=q[fnt];
        if(temp.fire)
        {
            for(int i=0; i<4; i++)
            {
                int nx=temp.x+dx[i];
                int ny=temp.y+dy[i];
                if(inMap(nx,ny) && !vis[nx][ny])
                {
                    vis[nx][ny]=1;
                    q[rear].x=nx;
                    q[rear].y=ny;
                    q[rear].fire=true;
                    q[rear].step=temp.step+1;
                    rear++;
                }
            }
        }
        else if(maze[temp.x][temp.y]=='J')
        {
            for(int i=0; i<4; i++)
            {
                int nx=temp.x+dx[i];
                int ny=temp.y+dy[i];
                if(!vis[nx][ny])
                {
                    vis[nx][ny]=1;
                    maze[nx][ny]='J';
                    q[rear].x=nx;
                    q[rear].y=ny;
                    q[rear].fire=false;
                    q[rear].step=temp.step+1;
                    if(!inMap(nx,ny))
                        return q[rear].step;
                    rear++;
                }
            }
        }
        fnt++;
    }
    return -1;
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        memset(vis,0,sizeof(vis));
        memset(maze,'.',sizeof(maze));
        scanf("%d %d",&r,&c);
        for(int i=1; i<=r; i++)
            scanf("%s",maze[i]+1);
        cnt=0;
        //for(int i=0; i<=r; i++)
        //{
        //    for(int j=0; j<=c; j++)
        //        printf("%c",maze[i][j]);
        //    printf("\n");
        //}
        for(int i=1; i<=r; i++)
        {
            for(int j=1; j<=c; j++)
            {
                if(maze[i][j]=='J')
                {
                    vis[i][j]=1;
                    start.x=i;
                    start.y=j;
                    start.step=0;
                    start.fire=false;
                }
                else if(maze[i][j]=='F')
                {
                    vis[i][j]=1;
                    fire[cnt].x=i;
                    fire[cnt].y=j;
                    fire[cnt].step=0;
                    fire[cnt++].fire=true;
                }
                else if(maze[i][j]=='#')
                    vis[i][j]=1;
            }
        }
        int ans=bfs();
        if(ans==-1)
            printf("IMPOSSIBLE\n");
        else
            printf("%d\n",ans);
    }
    return 0;
}


第二种方法自己想的,用了STL库~(还是觉得手写队列不如STL库来的省事唉...)

#include <cstdio>
#include <cstring>
#include <queue>
#define MAXN 1005
#define INF 0x3f3f3f3f
using namespace std;

int r,c;
char maze[MAXN][MAXN];
int vis[MAXN][MAXN];
int times[MAXN][MAXN];
int dx[]= {-1,0,0,1};
int dy[]= {0,-1,1,0};
int sx,sy;

struct Point
{
    int x;
    int y;
    int t;
}s,e;

queue <Point> q;

bool inMap(int x,int y)
{
    if(x>0 && x<=r && y>0 && y<=c)
        return true;
    return false;
}

void bfs_fire()
{
    while(!q.empty())
    {
        s=q.front();
        q.pop();
        for(int i=0; i<4; i++)
        {
            e.x=s.x+dx[i];
            e.y=s.y+dy[i];
            e.t=s.t+1;
            if(inMap(e.x,e.y) && !vis[e.x][e.y] && times[e.x][e.y]==INF)
            {
                times[e.x][e.y]=e.t;
                q.push(e);
            }
        }
    }
    //printf("bfs_fire done!\n");
}

int bfs_escape()
{
    s.x=sx;
    s.y=sy;
    s.t=0;
    vis[sx][sy]=1;
    q.push(s);
    while(!q.empty())
    {
        s=q.front();
        if(!inMap(s.x,s.y))
            return s.t;
        q.pop();
        for(int i=0; i<4; i++)
        {
            e.x=s.x+dx[i];
            e.y=s.y+dy[i];
            e.t=s.t+1;
            if(!vis[e.x][e.y] && e.t<times[e.x][e.y])
            {
                vis[e.x][e.y]=1;
                q.push(e);
            }
        }
    }
    return -1;
}

int main()
{
    int kase;
    scanf("%d",&kase);
    while(kase--)
    {
        memset(vis,0,sizeof(vis));
        memset(times,INF,sizeof(times));
        memset(maze,'.',sizeof(maze));
        while(!q.empty())
            q.pop();
        scanf("%d %d",&r,&c);
        for(int i=1; i<=r; i++)
            scanf("%s",maze[i]+1);
        for(int i=1; i<=r; i++)
        {
            for(int j=1; j<=c; j++)
            {
                if(maze[i][j]=='J')
                {
                    sx=i;
                    sy=j;
                }
                else if(maze[i][j]=='F')
                {
                    vis[i][j]=1;
                    times[i][j]=0;
                    s.x=i;
                    s.y=j;
                    s.t=0;
                    q.push(s);
                }
                else if(maze[i][j]=='#')
                    vis[i][j]=1;
            }
        }
        bfs_fire();
        int ans=bfs_escape();
        /*for(int i=0; i<=r; i++)
        {
            for(int j=0; j<=c; j++)
                printf("%d ",vis[i][j]);
            printf("\n");
        }*/
        if(ans==-1)
            printf("IMPOSSIBLE\n");
        else
            printf("%d\n",ans);
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值