UVA 11624 Fire! (技巧BFS)
2018-01-20 19:27
447 查看
题意:一个地图中有空地有墙,空地可以走。地图中有两中物品,一种是人,每分钟可以上下左右任走一格,一种是火,每分钟会向上下左右一起扩散。问人是否可以逃脱迷宫。逃脱迷宫的条件是到达边缘。
题解:我的思路比较奇特,我把火和人放在一个队列中处理了。这种处理方式是先处理火,然后再处理人。为什么这样是对的呢如下图:
就是队列中一定是一段人,然后一段火,这样保证人和火是同事进行的。单必须先把火比人先放进队列中,这样才能保证人不会走到火将要烧到的位置。如下图
若人先走的火,人会向左走,但是火也会向右走,意味着火和人会走到一个格子里。这是会烧死人的。
具体代码细节看注释。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<iostream>
#include<queue>
using namespace std;
const int maxn = 1010;
char map[maxn][maxn]; // 地图
int book[maxn][maxn]; // 标记数组,记录这点火或者人是否走过
struct node{
int x; //坐标x
int y; // 坐标y
int step; // 人的步数
int kind; // 用来区分是人还是火,1是人,0是火
};
queue<node> q;
int n,m,ans; // n,m表示长宽。ans表示火的个数
node ren; //记录人的起始位置
node fire[maxn]; // 记录火的起始位置
int mov[4][2] = {1,0,-1,0,0,1,0,-1}; // 移动数组
void bfs(){
node now,next;
for(int i = 0 ; i < ans ; i++){ // 先把火入队列
q.push(fire[i]);
}
q.push(ren); // 再把人放入队列
// cout<<ren.step<<endl;
while(!q.empty()){
now = q.front();
q.pop();
if(now.kind == 1 && (now.x == 0 || now.y== 0 || now.x == n-1 ||now.y == m-1)){ // 当是人到达边缘时
cout << now.step+1 << endl;
return ;
}
for(int i = 0 ; i < 4 ; i++){ // 对火对人进行移动
next.x = now.x+mov[i][0];
next.y = now.y+mov[i][1];
if(next.x < 0 || next.x >= n || next.y < 0 || next.y >= m || book[next.x][next.y] == 1 || map[next.x][next.y] == '#')//判断是否可走和越界
continue;
next.kind = now.kind; // 记录种类
book[next.x][next.y] = 1; // 标记已走
// printf("%d %d %d\n",next.x,next.y,next.step);
if(now.kind) // 若为人 顺带记录步数
next.step = now.step + 1;
q.push(next); //入队列
}
}
cout << "IMPOSSIBLE" << endl;
}
int main(){
int z;
cin >> z;
while(z--){
while(!q.empty()) q.pop(); // 清空很重要
memset(map,0,sizeof(map));
memset(book,0,sizeof(book));
ans = 0;
cin >> n >> m;
for(int i = 0 ; i < n ; i++)
cin >> map[i]; // 输入地图信息
for(int i = 0 ; i < n ; i++){
for(int j = 0 ; j < m ; j++){
if(map[i][j] == 'J'){ // 查找人的起始位置
ren.x = i;
ren.y = j;
ren.step = 0;
ren.kind = 1;
}
if(map[i][j] == 'F'){ // 查找所有火的起始位置
fire[ans].x = i;
fire[ans].y = j;
fire[ans].kind = 0;
fire[ans].step = 0;
ans ++;
book[i][j]=1;
}
}
}
bfs();
}
return 0;
}
/*
2
4 4
####
#JF#
#..#
#..#
3 3
###
#J.
#.F
*/
题解:我的思路比较奇特,我把火和人放在一个队列中处理了。这种处理方式是先处理火,然后再处理人。为什么这样是对的呢如下图:
就是队列中一定是一段人,然后一段火,这样保证人和火是同事进行的。单必须先把火比人先放进队列中,这样才能保证人不会走到火将要烧到的位置。如下图
若人先走的火,人会向左走,但是火也会向右走,意味着火和人会走到一个格子里。这是会烧死人的。
具体代码细节看注释。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<iostream>
#include<queue>
using namespace std;
const int maxn = 1010;
char map[maxn][maxn]; // 地图
int book[maxn][maxn]; // 标记数组,记录这点火或者人是否走过
struct node{
int x; //坐标x
int y; // 坐标y
int step; // 人的步数
int kind; // 用来区分是人还是火,1是人,0是火
};
queue<node> q;
int n,m,ans; // n,m表示长宽。ans表示火的个数
node ren; //记录人的起始位置
node fire[maxn]; // 记录火的起始位置
int mov[4][2] = {1,0,-1,0,0,1,0,-1}; // 移动数组
void bfs(){
node now,next;
for(int i = 0 ; i < ans ; i++){ // 先把火入队列
q.push(fire[i]);
}
q.push(ren); // 再把人放入队列
// cout<<ren.step<<endl;
while(!q.empty()){
now = q.front();
q.pop();
if(now.kind == 1 && (now.x == 0 || now.y== 0 || now.x == n-1 ||now.y == m-1)){ // 当是人到达边缘时
cout << now.step+1 << endl;
return ;
}
for(int i = 0 ; i < 4 ; i++){ // 对火对人进行移动
next.x = now.x+mov[i][0];
next.y = now.y+mov[i][1];
if(next.x < 0 || next.x >= n || next.y < 0 || next.y >= m || book[next.x][next.y] == 1 || map[next.x][next.y] == '#')//判断是否可走和越界
continue;
next.kind = now.kind; // 记录种类
book[next.x][next.y] = 1; // 标记已走
// printf("%d %d %d\n",next.x,next.y,next.step);
if(now.kind) // 若为人 顺带记录步数
next.step = now.step + 1;
q.push(next); //入队列
}
}
cout << "IMPOSSIBLE" << endl;
}
int main(){
int z;
cin >> z;
while(z--){
while(!q.empty()) q.pop(); // 清空很重要
memset(map,0,sizeof(map));
memset(book,0,sizeof(book));
ans = 0;
cin >> n >> m;
for(int i = 0 ; i < n ; i++)
cin >> map[i]; // 输入地图信息
for(int i = 0 ; i < n ; i++){
for(int j = 0 ; j < m ; j++){
if(map[i][j] == 'J'){ // 查找人的起始位置
ren.x = i;
ren.y = j;
ren.step = 0;
ren.kind = 1;
}
if(map[i][j] == 'F'){ // 查找所有火的起始位置
fire[ans].x = i;
fire[ans].y = j;
fire[ans].kind = 0;
fire[ans].step = 0;
ans ++;
book[i][j]=1;
}
}
}
bfs();
}
return 0;
}
/*
2
4 4
####
#JF#
#..#
#..#
3 3
###
#J.
#.F
*/
相关文章推荐
- UVA 11624 Fire! BFS+技巧
- uva 11624 - Fire!(bfs)
- uva 11624 - Fire! bfs
- uva 11624 - Fire!(Bfs)
- UVA - 11624 Fire! (2次bfs)
- UVA - 11624 Fire!两个bfs
- UVA - 11624 Fire!(15.10.10 搜索专题)bfs
- UVa 11624 Fire! / BFS
- UVA 11624 Fire! bfs
- UVA11624 Fire 两次BFS
- UVA - 11624 Fire! 两次BFS
- UVA 11624 Fire! bfs
- uva11624 Fire! BFS搜索 TWT Tokyo Olympic 2combo-2
- UVA11624-Fire!(两次bfs)
- UVa 11624 - Fire!(BFS)
- uva 11624 Fire!(bfs两次)
- UVA11624 Fire! BFS
- UVA - 11624 - Fire! (BFS的应用)
- uva 11624 Fire!(多源BFS)
- UVA 11624 Fire! (两次BFS 火追人 )