题目链接:UVa 11624 Fire!
今晚好不爽!
多源BFS。
先对人BFS一次,再对火BFS一次,可能有好多块火,那么先把所有火都加入队列中。判断一块区域谁先到,找最小的。
一个一个输入会超时,得一行一行输入。
scanf输入字符不会忽略回车和换行。
#include <iostream>
#include <queue>
#include <cstring>
#include <vector>
#include <stdio.h>
using namespace std;
const int MAX_N = 1000 + 100;
const int INF = (1 << 30);
const int dr[4] = {0,-1,1,0};
const int dc[4] = {1,0,0,-1};
struct Cell
{
int i,j;
Cell(int i,int j) : i(i),j(j){};
};
char _map[MAX_N][MAX_N];
int T,r,c,ans;
queue<Cell> q;
int vis[MAX_N][MAX_N][2],dis[MAX_N][MAX_N][2];
void bfs(int kind)
{
while(!q.empty())
{
Cell temp = q.front();
q.pop();
int a = temp.i;
int b = temp.j;
for(int i = 0;i < 4;i++)
{
int x = a + dr[i];
int y = b + dc[i];
if(x >= 0 && y >= 0 && x < r && y < c && _map[x][y] == '.' && !vis[x][y][kind])
{
q.push(Cell(x,y));
vis[x][y][kind] = 1;
dis[x][y][kind] = dis[a][b][kind] + 1;
}
}
}
}
void check(int i,int j)
{
if(!vis[i][j][0])
return;
if(!vis[i][j][1] || dis[i][j][0] < dis[i][j][1])
ans = min(ans,dis[i][j][0] + 1);
}
int main()
{
cin >> T;
while(T--)
{
vector<Cell> fires;
cin >> r >> c;
int jr,jc;
for(int i = 0;i < r;i++)
{
//scanf("%s",_map[i]);
cin >> _map[i];
for(int j = 0;j < c;j++)
{
//cin >> _map[i][j];
if(_map[i][j] == 'J')
{
jr = i;
jc = j;
_map[i][j] = '.';
}
else if(_map[i][j] == 'F')
{
fires.push_back(Cell(i,j));
_map[i][j] = '.';
}
}
}
memset(vis,0,sizeof(vis));
vis[jr][jc][0] = 1;
dis[jr][jc][0] = 0;
q.push(Cell(jr,jc));
bfs(0);
for(int i = 0;i < fires.size();i++)
{
vis[fires[i].i][fires[i].j][1] = 1;
dis[fires[i].i][fires[i].j][1] = 0;
q.push(fires[i]);
}
bfs(1);
ans = INF;
for(int i = 0;i < r;i++)
{
check(i,0);
check(i,c - 1);
}
for(int j = 0;j < c;j++)
{
check(0,j);
check(r - 1,j);
}
if(ans == INF)
cout << "IMPOSSIBLE" << endl;
else
cout << ans << endl;
}
return 0;
}