【题意】给出一个m*n的图,‘#’表示草坪,‘ . ’表示空地,然后可以选择在任意的两个草坪格子点火,火每 1 s会向周围四个格子扩散,问选择那两个点使得燃烧所有的草坪花费时间最小?
【分析】这个题目如果考虑技巧的话有点难度,但是鉴于数据范围比较小,我们可以暴力枚举任意的草坪所在的点,然后两个点压进队列里面BFS,去一个满足条件的最小值即可。
【总结】此题就是简单bfs,然而两个点同在相同时间的处理却比较少见,我也是通过此题学习到了这一方法!继续爆搜剪枝吧!武运昌隆。
【AC代码】
#include <stdio.h>
#include <vector>
#include <queue>
#include <ctype.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 11;
const int inf = 1<<30;
char maze[maxn][maxn];
bool vis[maxn][maxn];
int dir[4][2]={{0,1},{0,-1},{-1,0},{1,0}};
struct node{
int x,y,time;
node(){}
node(int x,int y,int time):x(x),y(y),time(time){}
};
vector<node>v;
int n,m,ans;
int bfs(node a,node b)
{
int cur_time = inf;
memset(vis,0,sizeof(vis));
queue<node>que;
a.time=b.time=0;
vis[a.x][a.y]=vis[b.x][b.y]=true;
que.push(a);que.push(b);
while(!que.empty())
{
a=que.front();
que.pop();
cur_time = a.time;
for(int i=0;i<4;i++)
{
b.x=a.x+dir[i][0];
b.y=a.y+dir[i][1];
b.time=a.time+1;
if(b.x>0&&b.x<=n&&b.y>0&&b.y<=m&&!vis[b.x][b.y]&&maze[b.x][b.y]=='#')
{
vis[b.x][b.y]=1;
que.push(b);
}
}
}
return cur_time;
}
int main()
{
int T,cas=1;
scanf("%d",&T);
while(T--)
{
v.clear();
scanf("%d%d",&n,&m);
ans = inf;
for(int i=1;i<=n;i++)
{
getchar();
for(int j=1;j<=m;j++)
{
scanf("%c",&maze[i][j]);
if(maze[i][j]=='#')v.push_back(node(i,j,0));
}
}
for(int i=0;i<(int)v.size();i++)
{
for(int j=i;j<(int)v.size();j++)
{
int tmp =bfs(v[i],v[j]);
bool *** = true;
for(int x=1;x<=n;x++)
{
for(int y=1;y<=m;y++)
{
if(maze[x][y]=='#'&&!vis[x][y])
{
***=false;
break;
}
if(!***)break;
}
}
if(***) ans = min(ans,tmp);
}
}
printf("Case %d: ",cas++);
if(ans==inf)
{
printf("-1\n");
}
else
{
printf("%d\n",ans);
}
}
return 0;
}