题意
两个熊孩子在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;
}