<题目链接>

题目大意:

你的任务是帮助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. JavaScript学习 - 基础(六) - DOM基础操作

    DOM: DOM定义了访问HTML 和XML 文档的标准:1.核心DOM 针对结构化文档的标准模型2.XMK DOM 针对XML文档的标准模型3.HTML DOM 针对HTML文档的标准模型 DOM节 ...

  2. Shiro会话管理器与验证码实现(十四)

    和shiro整合后,使用shiro的session管理,shiro提供sessionDao操作 会话数据. 配置sessionManager

  3. Debian 9 源配置

    Debian 9: deb http://mirrors.163.com/debian/ stretch main non-free contrib deb http://mirrors.163.co ...

  4. Cython的简单使用

    Cython是一个快速生成Python扩展模块的工具,从语法层面上来讲是Python语法和C语言语法的混血,当Python性能遇到瓶颈时,Cython直接将C的原生速度植入Python程序,这样使Py ...

  5. ES系列十八、FileBeat发送日志到logstash、ES、多个output过滤配置

    一.FileBeat基本概念 简单概述 最近在了解ELK做日志采集相关的内容,这篇文章主要讲解通过filebeat来实现日志的收集.日志采集的工具有很多种,如fluentd, flume, logst ...

  6. oracle 命令行

    背景 看到当初竟然记录了命令行,想想自己用了多久才知道了命令行,好像有几年了吧.当时还记得买了两本oracle9的管理书籍,就跟见了九阴真经一样,从头到尾熟悉了好几遍,不过也大部分忘了交给老师了.以下 ...

  7. saltstack自动化运维系列②之saltstack的数据系统

    saltstack自动化运维系列②之saltstack的数据系统 grains:搜集minion启动时的系统信息,只有在minion启动时才会搜集,grains更适合做一些静态的属性值的采集,例如设备 ...

  8. Java使用google开源工具Thumbnailator实现图片压缩

    <dependency> <groupId>net.coobird</groupId> <artifactId>thumbnailator</ar ...

  9. python下图像读取方式以及效率对比

    https://zhuanlan.zhihu.com/p/30383580 opencv速度最快,值得注意的是mxnet的采用多线程读取的方式,可大大加速

  10. Jmeter接口测试实例图文示例

    以getObjectByCode接口为例,用jmeter2.13来进行接口测试. 测试前准备: 测试工具及版本:jmeter 2.13 r1665067(须包含__MD5函数) 示例接口:8.1根据单 ...