题目链接 : Fire Game FZU - 2150
题意
有两个熊孩子,他们要在一片n*m空地上放火烧草地,’#’代表的是草地。他们可以在开始任选两个地点来防火(可以是同一点)火可以四方运动(每次耗费一个时间),如果最后火烧光了所有的草地,则输出他们需要等待的最小时间。否则输出-1。
思路
说起来很惭愧,我开始的想法很复杂,要对每个点进行BFS最后找到终点。总之思路很混乱。
后来看到了大神的题解,才恍然大悟。只需暴力枚举两个起始点,再BFS即可,虽然时间复杂度很高,但是数据小啊,n才<= 10。 BFS 完了再进行判断有无草地剩余即可。
代码
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int MAXN = (int) 13;
const int INF = (int) 0x3f3f3f3f;
int n,m;
char pic[MAXN][MAXN];
int vis[MAXN][MAXN];
struct Node {
int x,y,step;
Node(int x = 0,int y = 0,int s = 0):x(x),y(y),step(s){}
};
int dir[4][2] = {
{1,0},
{-1,0},
{0,1},
{0,-1},
};
int bfs(int x1,int y1,int x2,int y2){
memset(vis,0,sizeof(vis));
queue<Node> qu;
qu.push(Node(x1,y1,0));
vis[x1][y1] = 1;
qu.push(Node(x2,y2,0));
vis[x2][y2] = 1;
Node k;
while (!qu.empty()){
k = qu.front();
qu.pop();
for (int i = 0;i < 4;i ++){
int dx = k.x + dir[i][1];
int dy = k.y + dir[i][0];
if (dx < 1 || dx > n || dy < 1 || dy > m || vis[dx][dy] || pic[dx][dy] == '.') continue;
vis[dx][dy] = 1;
qu.push(Node(dx,dy,k.step+1));
}
}
int flag = 0;
for (int i = 1;i <= n;i ++)
for (int j = 1;j <= m;j ++){
if (pic[i][j] == '#' && vis[i][j] == 0)
flag = 1;
}
if (flag)return INF;
else return k.step;
}
int main()
{
int T;
scanf("%d",&T);
for (int ca = 1;ca <= T;ca ++){
scanf("%d %d\n",&n,&m);
for (int i = 1;i <= n;i ++){
scanf("%s",pic[i]+1);
}
int tim = INF;
for (int i = 1;i <= n;i ++)
for (int j = 1;j <= m;j ++)
for (int ii = 1;ii <= n;ii ++)
for (int jj = 1;jj <= m;jj ++)
if (pic[i][j] == '#' && pic[ii][jj] == '#')
tim = min(bfs(i,j,ii,jj),tim);
if (tim == INF)tim = -1;
printf("Case %d: %d\n",ca,tim);
}
}