UVaOJ-11624-Fire! 解题报告

来源:互联网 发布:唱歌声卡软件下载 编辑:程序博客网 时间:2024/05/22 16:45

       一道十分优美的搜索题,暴露了我对BFS了解的还不够。题意:Joe要逃离一个迷宫,迷宫中有地方起火了,在火开始燃烧的时候Joe也开始逃,火的蔓延方式与Joe的行动方式一样,都是1个单位时间可以往上下左右四个方向各走一格。另外,迷宫内有墙,Joe与火都无法穿墙。现在给你一个图,请问Joe能否从迷宫的边界处逃出而不被火烧到,如果能的话请输出最短的逃脱时间,不能的话输出“IMPOSSIBLE”。其中,‘F’代表火,‘J’代表Joe,‘#’代表墙。


       我的解题思路:这题首先注意的就是,起火点可能不止一个,也可能没有起火点。其次是如果一个起火点被四周的墙给封闭起来了,那么这个火就相当于没有用了。为了判断Joe走到某个点时这个点是否已经起火,我们需要知道每个点起火的时间。通过对每个初始起火点进行BFS就可以知道每个点的起火时间了,最开始我是每个起火点都BFS一次,然后TLE了,后来才发现,其实可以把每个初始起火点当成一个起火点的邻节点加入队列,这样就只进行了一次BFS,从而获得了每个点起火的时间(如果有些点不会起火,那么这些点的时间就是初始化的INF)。最后从Joe的起点开始BFS一次,如果走到下一个点时那个点已经或者刚好着火了那就不能走,墙也不能走,只要走到边界就说明可以走出迷宫了。


       我的解题代码:BFS解题

#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#include <queue>using namespace std;#define N 1001#define INF 999999999struct point        //定义点结构体{    int x, y;   //坐标    int step;   //步数,相当于时间};int dx[] = {1, -1, 0, 0};   //方向向量int dy[] = {0, 0, -1, 1};   //方向向量int n, m, t;char map[N][N];int vis[N][N];          //记录火或者人到达点花费的最少时间point start, fire;      //起点和起火处queue <point> q;void Read();            //输入void Init();            //初始化void FireBfs();         //先进行起火处的Bfsvoid DataProcess();     //进行人的Bfs判断能否逃离以及最少逃离时间int main(){    scanf("%d", &t);    while (t--)    {        Read();        Init();        DataProcess();    }    return 0;}void Read(){    scanf("%d %d", &n, &m);    for (int i=0; i<n; ++i)    {        scanf("%s", map[i]);    }    return;}void Init(){    while (!q.empty()) q.pop();     //清空队列    for (int i=0; i<n; ++i)    {        for (int j=0; j<m; ++j)        {            vis[i][j] = INF;        //初始vis            if (map[i][j] == 'J')            {                start.x = i;                start.y = j;                start.step = 0;                vis[i][j] = 0;            }            else if (map[i][j] == 'F')            {                fire.x = i;                fire.y = j;                fire.step = 0;                q.push(fire);           //加入队列准备进行火的Bfs                vis[i][j] = 0;            }        }    }    return;}void FireBfs(){    point a, b;    while (!q.empty())    {        a = q.front();        q.pop();        for (int j=0; j<4; ++j)        {            int nx = a.x + dx[j];            int ny = a.y + dy[j];            if (nx < 0 || nx >= n || ny < 0 || ny >= m) continue;       //越界            if (map[nx][ny] == '#' || vis[nx][ny] <= a.step + 1) continue;  //墙或者已经走过的点            b.x = nx;            b.y = ny;            b.step = vis[nx][ny] = a.step + 1;            q.push(b);        }    }    return;}void DataProcess(){    point a, b;    FireBfs();    q.push(start);      //将人的起点加入队列准备Bfs    while (!q.empty())    {        a = q.front();        q.pop();        for (int i=0; i<4; ++i)        {            int nx = a.x + dx[i];            int ny = a.y + dy[i];            if (nx < 0 || nx >= n || ny < 0 || ny >= m)     //成功走到边界            {                printf("%d\n", a.step + 1);                return;            }            if (map[nx][ny] == '#' || vis[nx][ny] <= a.step + 1) continue;  //遇到墙或者该点起火或者走过            b.x = nx;            b.y = ny;            b.step = vis[nx][ny] = a.step + 1;            q.push(b);        }    }    puts("IMPOSSIBLE");    return;}

0 0
原创粉丝点击