<题目链接>

题目大意:

你的任务是帮助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. Java SE之字符串常量池

    Reference Document: 什么是字符串常量池?   http://www.importnew.com/10756.html[Recommend] Java常量池理解与总结   http: ...

  2. Git查看单个文件修改历史

    1 命令 git log --pretty=oneline  文件名 ➜ admin git:(feature/v1.5.0_20181202_group) git log --pretty=onel ...

  3. Pytorch 各种奇葩古怪的使用方法

    h1 { counter-reset: h2counter; } h2 { counter-reset: h3counter; } h3 { counter-reset: h4counter; } h ...

  4. 推荐系统之协同过滤的原理及C++实现

    1.引言 假如你经营着一家网店,里面卖各种商品(Items),有很多用户在你的店里面买过东西,并对买过的Items进行了评分,我们称之为历史信息,现在为了提高销售量,必须主动向用户推销产品,所以关键是 ...

  5. 【windows核心编程】远程线程DLL注入

    15.1 DLL注入 目前公开的DLL注入技巧共有以下几种: 1.注入表注入 2.ComRes注入 3.APC注入 4.消息钩子注入 5.远线程注入 6.依赖可信进程注入 7.劫持进程创建注入 8.输 ...

  6. 一文看懂汽车电子ECU bootloader工作原理及开发要点

    随着半导体技术的不断进步(按照摩尔定律),MCU内部集成的逻辑功能外设越来越多,存储器也越来越大.消费者对于汽车节能(经济和法规对排放的要求)型.舒适性.互联性.安全性(功能安全和信息安全)的要求越来 ...

  7. Vulcan 基于Meteor的APollO框架 , grapesjs 用于可视化生成Html 页面

    Vulcan 基于Meteor的APollO框架 :http://vulcanjs.org/ grapesjs 用于可视化生成Html    http://grapesjs.com/

  8. Jenkins与网站代码上线解决方案【转】

    转自 Jenkins与网站代码上线解决方案 - 惨绿少年 https://www.nmtui.com/clsn/lx524.html 1.1 前言 Jenkins是一个用Java编写的开源的持续集成工 ...

  9. java多线程系列五、并发容器

    一.ConcurrentHashMap 1.为什么要使用ConcurrentHashMap 在多线程环境下,使用HashMap进行put操作会引起死循环,导致CPU利用率接近100%,HashMap在 ...

  10. DES加密模式详解

    DES加密模式详解 http://www.cnblogs.com/Lawson/archive/2012/05/20/2510781.html http://www.blogjava.net/wayn ...