题意
两个熊孩子在n*m的平地上放火玩,#表示草,两个熊孩子分别选一个#格子点火,火可以向上向下向左向右在有草的格子蔓延,点火的地方时间为0,蔓延至下一格的时间依次加一。求烧完所有的草需要的最少时间。如不能烧完输出-1。
解题
枚举两个人所选的#格子。O(n^2*m^2)的复杂度。
从所枚举的两个格子开始BFS,BFS过程中计数所遍历的#格子数cnt以及遍历到某个#格子的时刻。BFS完好比较cnt是否与平地#格子数相等。
AC代码
//765ms 0.2MB
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <queue>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn=12;
int sum;//草总数
int cnt;//遍历到的草数
int n,m;
char s[maxn][maxn];
bool vis[maxn][maxn];
struct node
{
int x,y,t;
node(int x,int y,int t):x(x),y(y),t(t){}
};
int dir[4][2]={0,1,0,-1,1,0,-1,0};
bool valid(int x,int y)
{
return x>=0 && x<n && y>=0 && y<m && s[x][y]=='#'&& !vis[x][y];
}
int bfs(int x,int y,int fx,int fy)
{
int ans=-INF;
cnt=0;
memset(vis,false,sizeof(vis));
vis[x][y]=vis[fx][fy]=true;
queue<node> Q;
Q.push(node(x,y,0));
if(x!=fx || y!=fy)//注意不要重复入队列,否则会导致cnt的值错误
Q.push(node(fx,fy,0));
while(!Q.empty())
{
node now=Q.front();Q.pop();
cnt++;
int u=now.x,v=now.y,t=now.t;
ans=max(ans,t);
for(int i=0;i<4;i++)
{
int fu=u+dir[i][0],fv=v+dir[i][1];
if(!valid(fu,fv)) continue;
vis[fu][fv]=true;
Q.push(node(fu,fv,t+1));
}
}
if(cnt==sum) return ans;
return INF;
}
int main()
{
int T,kase=0;
cin>>T;
while(T--)
{
cin>>n>>m;
sum=0;
int ans=INF;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
{
cin>>s[i][j];
if(s[i][j]=='#') sum++;
}
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
{
if(s[i][j]=='.') continue;
for(int fi=0;fi<n;fi++)
for(int fj=0;fj<m;fj++)
{
if(s[fi][fj]=='.') continue;
ans=min(ans,bfs(i,j,fi,fj));
}
}
ans=ans==INF?-1:ans;
cout<<"Case "<<++kase<<": "<<ans<<endl;
}
return 0;
}