<题目链接>

题目大意:

你的任务是帮助J走出一个大火蔓延的迷宫。J每分钟可以超上下左右四个方向移动,而所有着火的格子每一分钟都会往四个方向蔓延一格。迷宫中有一些障碍,J和火都无法进入。当J走出迷宫的边界时,逃离成功。

解题分析:

注意,刚开始不一定只有一个格子着火。看到这道题,很容易想到要用BFS,火的蔓延和人的行走都用BFS模拟一下。先将火蔓延到所有点的最短时间通过bfs模拟求出来,然后再对人行走的过程用bfs进行模拟,从而计算出该人到达每个点的最短时间,如果人到达该点的最短时间晚于火到达的最短时间,那么该点不能走。根据这些,判断该人是否能够达到边界,即逃出迷宫。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm> using namespace std; const int MAXN = ;
const int INF = 0x3f3f3f3f;
const int dx[] = {-, , , };
const int dy[] = {, -, , }; struct node{
node (int xx, int yy, int dd) {
x = xx;
y = yy;
d = dd;
}
int x, y, d;
}; char g[MAXN][MAXN];
int vf[MAXN][MAXN], vm[MAXN][MAXN];
int T[MAXN][MAXN]; //记录火蔓延到的点的最短时间,以便判断人是否是在火烧到该点之前就能够到达该点
int r, c, sx, sy; queue<node> qf; void bfs_fire() { //bfs模拟火的蔓延过程
while (!qf.empty()) {
node u = qf.front();
qf.pop();
node v = u;
for (int i = ; i < ; i++){
int tx = u.x + dx[i];
int ty = u.y + dy[i];
if (tx < || tx >= r || ty < || ty >= c || g[tx][ty] == '#') continue;
if (!vf[tx][ty]) {
vf[tx][ty] = ;
T[tx][ty] = u.d+; //记录火蔓延到的点的最短时间,以便判断人是否是在火烧到该点之前就能够到达该点
qf.push(node(tx,ty,u.d+));
}
}
}
} int bfs_man() {
queue<node> qm;
while (!qm.empty()) qm.pop();
node s(sx, sy, );
qm.push(s);
memset(vm, , sizeof(vm));
vm[sx][sy] = ;
while (!qm.empty()) {
node u = qm.front();
qm.pop();
if (u.x == || u.x == r - || u.y == || u.y == c - ) //达到边界
return u.d + ;
node v = u;
for (int i = ; i < ; i++) {
int tx = u.x + dx[i];
int ty = u.y + dy[i];
if (tx < || tx >= r || ty < || ty >= c || g[tx][ty] == '#') continue;
if (u.d + >= T[tx][ty]) continue; //如果在这个人来之前,火就烧到了这里,则这个点不能走,这里很关键
if (!vm[tx][ty]){ //如果这个点能走且该人之前没走过
vm[tx][ty] = ;
qm.push(node(tx,ty,u.d+));
}
}
}
return -;
} int main() {
int cas;
scanf("%d", &cas);
while (cas--) {
scanf("%d%d", &r, &c);
for (int i = ; i < r; i++)
scanf("%s", g[i]); while(!qf.empty()) qf.pop();
memset(vf, , sizeof(vf));
memset(T, INF, sizeof(T)); for (int i = ; i < r; i++) {
for (int j = ; j < c; j++) {
if (g[i][j] == 'J') {
sx = i;
sy = j;
}
if (g[i][j] == 'F') { //注意,着火点不止有一个
node tmp(i, j, );
vf[i][j] = ;
T[i][j] = ;
qf.push(tmp);
}
}
} bfs_fire(); //先提前计算,火能够蔓延到的点的最短时间
int ans = bfs_man();
if (ans == -)
printf("IMPOSSIBLE\n");
else
printf("%d\n", ans);
}
return ;
}

下面还有一种想法:

通过模拟,火先蔓延一步,人再走一步,因为只有最新蔓延的火,才会对下一步的蔓延到其他点做出贡献,所以,每次只记录新蔓延出来的点,如下面的que[]数组模拟队列,用head和topend来控制只对新蔓延的点进行烧火模拟,达到“火蔓延一步”,“人走一步”的效果。但是下面的这段代WA了,不知道是不是我的思路有问题,先记录着。

#include <cstdio>
#include <cstring>
#include <queue>
#include <iostream>
#include <algorithm>
using namespace std; const int maxn=+; int n,m,flag,ans;
char mpa[maxn][maxn];
int vis[maxn][maxn];
int head,topend; int dir[][]={,,,,-,,,-}; struct node{
int x,y;
int step;
node(int a=,int b=,int c=){
x=a,y=b,step=c;
}
}st,et,que[maxn*maxn]; void fire(){ //每次只更新一步
int top=topend;
while(head<top){ //上一次刚蔓延到的所有点,用小于是因为每次蔓延到新的点都是topend++
node now=que[head];
head++;
for(int k=;k<;k++){
int xx=now.x+dir[k][];
int yy=now.y+dir[k][]; //超界或者已经蔓延过的点,就不用再蔓延了
if(xx<||xx>n||yy<||yy>m||mpa[xx][yy]!='.')continue;
mpa[xx][yy]='*';
que[topend++]=node(xx,yy,now.step); //火烧的过程不算在走的步数中
}
}
} void bfs(){
memset(vis,,sizeof(vis));
queue<node>q;
vis[st.x][st.y]=;
q.push(st);
while(!q.empty()){
node now=q.front();
q.pop();
if(now.x==||now.x==n||now.y==||now.y==m){
flag=;
ans=now.step;
return;
}
fire(); //模拟烧火过程
for(int k=;k<;k++){
int xx=now.x+dir[k][];
int yy=now.y+dir[k][];
if(xx<||xx>n||yy<||yy>m||vis[xx][yy]||mpa[xx][yy]!='.')continue;
vis[xx][yy]=;
q.push(node(xx,yy,now.step+));
}
}
} int main(){
int t;scanf("%d",&t);
while(t--){
scanf("%d %d",&n,&m);
memset(mpa,,sizeof(mpa));
memset(que,,sizeof(que));
head=topend=;
for(int i=;i<=n;i++){
scanf("%s",mpa[i]+);
for(int j=;j<=m;j++){
if(mpa[i][j]=='J'){
st=node(i,j,);
mpa[i][j]='.';
}
if(mpa[i][j]=='F'){
et=node(i,j,);
que[topend++]=et; //着火点不止有一个
mpa[i][j]='*';
}
}
}
flag=;
bfs();
if(flag){
printf("%d\n",ans+);
}
else printf("IMPOSSIBLE\n");
}
return ;
}

2018-08-29

UVA 11624-Fire!【双BFS】的更多相关文章

  1. UVA 11624 - Fire! 图BFS

    看题传送门 昨天晚上UVA上不去今天晚上才上得去,这是在维护么? 然后去看了JAVA,感觉还不错昂~ 晚上上去UVA后经常连接失败作死啊. 第一次做图的题~ 基本是照着抄的T T 不过搞懂了图的BFS ...

  2. UVa 11624 Fire!(BFS)

    Fire! Time Limit: 5000MS   Memory Limit: 262144KB   64bit IO Format: %lld & %llu Description Joe ...

  3. (简单) UVA 11624 Fire! ,BFS。

    Description Joe works in a maze. Unfortunately, portions of the maze have caught on fire, and the ow ...

  4. UVA - 11624 Fire! 【BFS】

    题意 有一个人 有一些火 人 在每一秒 可以向 上下左右的空地走 火每秒 也会向 上下左右的空地 蔓延 求 人能不能跑出来 如果能 求最小时间 思路 有一个 坑点 火是 可能有 多处 的 样例中 只有 ...

  5. UVA - 11624 Fire! 双向BFS追击问题

    Fire! Joe works in a maze. Unfortunately, portions of the maze have caught on fire, and the owner of ...

  6. uva 11624 Fire! 【 BFS 】

    按白书上说的,先用一次bfs,求出每个点起火的时间 再bfs一次求出是否能够走出迷宫 #include<cstdio> #include<cstring> #include&l ...

  7. BFS(两点搜索) UVA 11624 Fire!

    题目传送门 /* BFS:首先对火搜索,求出火蔓延到某点的时间,再对J搜索,如果走到的地方火已经烧到了就不入队,直到走出边界. */ /******************************** ...

  8. UVa 11624 Fire!(着火了!)

    UVa 11624 - Fire!(着火了!) Time limit: 1.000 seconds Description - 题目描述 Joe works in a maze. Unfortunat ...

  9. UVA - 11624 Fire! bfs 地图与人一步一步先后搜/搜一次打表好了再搜一次

    UVA - 11624 题意:joe在一个迷宫里,迷宫的一些部分着火了,火势会向周围四个方向蔓延,joe可以向四个方向移动.火与人的速度都是1格/1秒,问j能否逃出迷宫,若能输出最小时间. 题解:先考 ...

  10. UVA 11624 Fire!【两点BFS】

    Joe works in a maze. Unfortunately, portions of the maze have caught on fire, and the owner of the m ...

随机推荐

  1. GET和POST有什么区别?及为什么网上多数答案都是错的(转载)

    这仅仅是我认为比较好的关于get和post区别的解答,然后把作者的一些文字踢除留下比较干的部分. 作者:南柯之石链接:http://www.cnblogs.com/nankezhishi/archiv ...

  2. Java读取Excel文件转换成JSON并转成List——(七)

    Jar包

  3. SpringBoot集成Spring Security(授权与认证)

    ⒈添加starter依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifact ...

  4. u盘的一些理解

    U盘是由主控板+FLASH+外壳组成的,当主控板焊接上空白FLASH后插入电脑,因为没有相应的数据,  量产工具 电脑只能识别到主控板,而无法识别到FLASH,所以这时候电脑上显示出U盘盘符,但是双击 ...

  5. MHL技术剖析,比HDMI更强【转】

    转自:http://blog.chinaunix.net/uid-22030783-id-3294750.html MHL这个只是经常听说,没有见过的东西,现在已经非常火热了,我们才刚刚开始做,人家三 ...

  6. 解析如何在C语言中调用shell命令的实现方法【转】

    本文转自:http://www.jb51.net/article/37404.htm 1.system(执行shell 命令)相关函数 fork,execve,waitpid,popen表头文件 #i ...

  7. C# Excel使用NPOI

    程序处理excel使用using Microsoft.Office.Interop.Excel方式,运行程序需要电脑安装excel,而且excel版本还需要一样,使用起来不方便.使用NPOI不用电脑安 ...

  8. PhpStrom添加调试功能

    要给PhpStrom添加调试功能,需要安装Xdebug,网址:https://xdebug.org/ 1.如何下载对应thinkphp版本号的Xdebug呢 创建一个php文件,在里面输入phpinf ...

  9. Map<String,String>集合的四种遍历方式 其中有一种针对大容量的数据集合

  10. Reactor模型-多线程程版

    1.概述 在Reactor单线程版本的设计中,I/O任务乃至业务逻辑都由Reactor线程来完成,这无疑增加了Reactor线程的负担,高负载情况下必然会出现性能瓶颈.此外,对于多处理器的服务器来说, ...