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
- UVaOJ-11624-Fire! 解题报告
- uvaoj 11624 - Fire!
- UvaOJ 401——解题报告
- UVaOJ-11488-Hyper Prefix Sets 解题报告
- UVaOJ-11992-Fast Matrix Operations 解题报告
- UVaOJ-11827-Maximum GCD 解题报告
- UVaOJ-10539-Almost Prime Numbers 解题报告
- UVaOJ-10791-Minimum Sum LCM 解题报告
- UVaOJ-10200-Prime Time 解题报告
- UVaOJ-11752-The Super Powers 解题报告
- HDU 2469 Fire-control System解题报告
- Fire net 之DFS解题报告
- Fire net之贪心解题报告
- fzu 2150 - Fire Game解题报告
- UVaOJ-10168-Summation of Four Primes 解题报告
- UVa 1432 Fire-Control System 解题报告(离散化 + 扫描)
- YT04-贪心课堂练习-1004—Fire Net-(6.14日-烟台大学ACM预备队解题报告)
- 解题报告
- 七步从Angular.JS菜鸟到专家(2):Scopes(1)
- 觉得有点自豪的一些项目
- 七步从Angular.JS菜鸟到专家(3):数据绑定和AJAX(1)
- Ado.net中DataSet和SqlDataReader的区别
- EL与OGNL的对比使用
- UVaOJ-11624-Fire! 解题报告
- ??html阻止事件冒泡
- PAT_B_字符串-06. IP地址转换(20)
- 七步从AngularJS菜鸟到专家(4和5):指令和表达式(1)
- 七步从AngularJS菜鸟到专家(6):服务(1)
- poj1815+sap+枚举+最小割点集
- 理解互斥量和信号量 .
- 七步从AngularJS菜鸟到专家(7):Routing(1)
- [python]去除列表中重复元素