【题意】给出一个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 fuck = true; for(int x=1;x<=n;x++) { for(int y=1;y<=m;y++) { if(maze[x][y]=='#'&&!vis[x][y]) { fuck=false; break; } if(!fuck)break; } } if(fuck) ans = min(ans,tmp); } } printf("Case %d: ",cas++); if(ans==inf) { printf("-1\n"); } else { printf("%d\n",ans); } } return 0; }