bfs简单题,和最简单粗暴的迷宫题就差了一个人走的同时火在蔓延。咱的实现是在同一时间内先广搜火的路径再广搜人的路径。
分析的话,也可以分开,先对火单独做一次bfs,把所有的可走路径上火最快到达的时间求出来,然后人走bfs的时候再与人走到此格的时间和火烧到此点的时间进行对比,实现起来更清晰一些。
PS:然而看错题以为着火点只有一个。贡献了那么多次wa我这也是没谁了。引以为戒……以后一定要好好读题Orz
#include <iostream>
#include <string>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <ctime>
#include <cmath>
#include <queue>
#include <map>
#define M 1005
#define INF 0x3f3f3f3f
using namespace std;
struct node
{
int x, y, step;
}F[M * M],st;
int cnt, cnt1, R, C, f[4][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
char maze[M][M];
bool vis[M][M], visfire[M][M];
int bfs()
{
node fires, tmp, t;
memset(vis, false, sizeof(vis));
memset(visfire, false, sizeof(visfire));
queue<node> Q, fire;
Q.push(st);
for(int i = 0; i < cnt; i++)
{
fire.push(F[i]);
visfire[F[i].x][F[i].y] = true;
}
cnt1 = 1;
vis[st.x][st.y] = true;
while(cnt1)//在这里等同于while(!Q.empty())
{
while(cnt--)//添加当前时间点火蔓延到的地点
{
fires = fire.front();
fire.pop();
for(int i = 0; i < 4; i++)
{
t.x = fires.x + f[i][0];
t.y = fires.y + f[i][1];
if(!visfire[t.x][t.y] && maze[t.x][t.y] != '#' && t.x > 0 && t.y > 0 && t.x <= R && t.y <= C)
{
visfire[t.x][t.y] = true;
fire.push(t);
}
}
}
cnt = fire.size();
while(cnt1--)//当前时间点火蔓延到的地点求完后,再求当前人可以走的所有路径
{
tmp = Q.front();
Q.pop();
for(int i = 0; i < 4; i++)
{
t.x = tmp.x + f[i][0];
t.y = tmp.y + f[i][1];
t.step = tmp.step + 1;
if(t.x <= 0 || t.y <= 0 || t.x > R || t.y > C)//一旦走到迷宫外就返回时间值
{
return t.step;
}
if(!vis[t.x][t.y] && !visfire[t.x][t.y] && maze[t.x][t.y] != '#')
{
vis[t.x][t.y] = true;
Q.push(t);
}
}
}
cnt1 = Q.size();
}
return -1;
}
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
scanf("%d %d", &R, &C);
int i, j;
cnt = 0;
for(i = 1; i <= R; i++)
{
scanf("%s", maze[i] + 1);
for(j = 1; j <= C; j++)
{
if(maze[i][j] == 'J')
{
st.x = i;
st.y = j;
}
else if(maze[i][j] == 'F')
{
F[cnt].x = i;
F[cnt++].y = j;
}
}
}
int ans = bfs();
if(ans != -1)
printf("%d\n", ans);
else
printf("IMPOSSIBLE\n");
}
return 0;
}
运行结果: