直接放题目链接吧UVA11624
一开始比较犯晕,不知道怎么下手,因为火和人都在动,后来看了眼分析瞬间有了思路,人是受火的牵制的,先让火自由蔓延,即先对火跑一遍BFS,得到火到达每一块地方的时间,然后人再跑一遍BFS,根据火到达每一块地方的时间来判断能不能走,只要越过边界就直接退出,即得到了最小时间。需要注意的是,着火点F不止有一个,一开始我对每一个F点都跑一遍BFS,意料之中超时,然后改进了一下,直接把F点加入队列就行了,不用挨个跑
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int N = 1e3 + 5;
const int INF = 1e9; //时间最大值
struct node
{
int x, y, time;
};
int r, c;
char map[N][N];
bool vis[N][N];
int ftime[N][N]; //到达每一块地方的时间,初始化为INF
int xx[4] = {1, 0, 0, -1};
int yy[4] = {0, 1, -1, 0};
queue<node> qf; //存放火的全局队列
void Fire_BFS()
{
struct node t, u;
while(!qf.empty())
{
u = qf.front();
qf.pop();
for(int i = 0; i < 4; i++)
{
t.x = u.x + xx[i];
t.y = u.y + yy[i];
if(t.x >= 0 && t.x < r && t.y >= 0 && t.y < c && map[t.x][t.y] != '#')
{
if(!vis[t.x][t.y])
{
t.time = u.time + 1;
qf.push(t);
vis[t.x][t.y] = 1;
if(t.time < ftime[t.x][t.y]) //当前时间比之前的小,更新时间
ftime[t.x][t.y] = t.time;
}
}
}
}
}
int Joe_BFS(int jx, int jy)
{
queue<node> q;
struct node t, u;
memset(vis, 0, sizeof(vis));
t.x = jx;
t.y = jy;
t.time = 0;
q.push(t);
vis[jx][jy] = 1;
while(!q.empty())
{
u = q.front();
q.pop();
for(int i = 0; i < 4; i++)
{
t.x = u.x + xx[i];
t.y = u.y + yy[i];
t.time = u.time + 1;
if(t.x >= 0 && t.x < r && t.y >= 0 && t.y < c)
{
if(map[t.x][t.y] != '#' && t.time < ftime[t.x][t.y] && !vis[t.x][t.y])
{ //人到达一个地方的时间一定要比火到达的时间要小
q.push(t);
vis[t.x][t.y] = 1;
}
}
else
return t.time;
}
}
return 0;
}
int main()
{
int t;
int jx, jy;
scanf("%d", &t);
while(t--)
{
scanf("%d%d", &r, &c);
for(int i = 0; i < r; i++)
scanf("%s", map[i]);
for(int i = 0; i < r; i++)
for(int j = 0; j < c; j++)
ftime[i][j] = INF; //初始化时间
while(!qf.empty()) //清空队列
qf.pop();
struct node temp;
for(int i = 0; i < r; i++)
for(int j = 0; j < c; j++)
{
if(map[i][j] == 'F')
{
temp.x = i;
temp.y = j;
temp.time = 0;
qf.push(temp); //每一个着火点入队
vis[i][j] = 1;
}
else if(map[i][j] == 'J')
{
jx = i;
jy = j;
}
}
memset(vis, 0, sizeof(vis));
Fire_BFS();
int cnt = Joe_BFS(jx, jy);
if(cnt)
printf("%d\n", cnt);
else
printf("IMPOSSIBLE\n");
}
return 0;
}