题目大意:有一块空地上有些草堆‘#’,两个小伙伴想要在这片地上玩耍,然后就要烧掉这些草堆,相邻的草堆可以相互引燃,两个人可以分别选择一块草堆点燃,问说最少需要多少时间才能烧光草堆(每人只能点一次)
解题思路:枚举两个位置同时做为起点,然后BFS,注意有一个坑点就是说草堆的个数少于2的时候,枚举不到两个起点,但是是可以烧光草堆的。
#include <stdio.h>
#include <string.h>
#include <queue>
#include <algorithm>
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 20;
const int dir[4][2] = { {0, 1}, {0, -1}, {1, 0}, {-1, 0}};
struct point {
int x, y;
point() {}
point(int a, int b) { x = a; y = b; }
};
int l, r, d[N][N], tmp;
char g[N][N];
void init() {
memset(g, 0, sizeof(g));
tmp = 0;
scanf("%d%d%*c", &r, &l);
for (int i = 0; i < r; i++) {
gets(g[i]);
for (int j = 0; j < l; j++) if (g[i][j] == '#') tmp++;
}
}
int bfs(int x1, int y1, int x2, int y2) {
memset(d, INF, sizeof(d));
d[x1][y1] = d[x2][y2] = 0;
point k, c;
queue<point> q;
q.push(point(x1, y1));
q.push(point(x2, y2));
while ( !q.empty() ) {
k = q.front(); q.pop();
for (int i = 0; i < 4; i++) {
c.x = k.x + dir[i][0]; c.y = k.y + dir[i][1];
if (c.x < 0 || c.x >= r || c.y < 0 || c.y >= l) continue;
if (g[c.x][c.y] != '#') continue;
if (d[c.x][c.y] > d[k.x][k.y] + 1) {
d[c.x][c.y] = d[k.x][k.y] + 1;
q.push(c);
}
}
}
int ans = 0;
for (int i = 0; i < r; i++) {
for (int j = 0; j < l; j++) if (g[i][j] == '#') {
ans = max(ans, d[i][j]);
}
}
return ans;
}
int solve() {
if (tmp <= 2) return 0;
int ans = INF;
for (int i = 0; i < r; i++) {
for (int j = 0; j < l; j++) if (g[i][j] == '#') {
for (int k = 0; k < r; k++) {
for (int t = 0; t < l; t++) {
if (k == i && t <= j) continue;
if (g[k][t] == '#')
ans = min(ans, bfs(i, j, k, t));
}
}
}
}
return ans == INF ? -1 : ans;
}
int main () {
int cas;
scanf("%d", &cas);
for (int i = 1; i <= cas; i++) {
init();
printf("Case %d: %d\n", i, solve());
}
return 0;
}