!!!!没提交上,只是写下自己的想法。
题意:给定一个n*m的图形(1~10),只包含'#'和'.'。保证至少含有一个'#',有两个人,最开始在t=0的时候各选一个'#'点燃(选的位置可以一样),t+1时刻它的上下左右也会点燃,问最少多少分钟能点完,如果不能点完,则输出-1。
题解:连通块数cnt>=3时输出-1;=2的时候暴力每个连通块(枚举每个连通块的每个“#‘作为起点);=1的时候每次枚举两个点。
1)双起点bfs:最开始queue放入两个点就好了。
代码(FZU_OJ有毒,还没提交上,但是应该是对的):
//最后的版本(自然不是正确的,只是待修改的)
#include <bits/stdc++.h>
// #define int long long
#define pb push_back
#define mst(a, i) memset(a, i, sizeof(a))
#define dbg(x) cout << #x << "===" << x << endl
using namespace std;
void read(int &x) {
int res = 0, f = 1;
char c = getchar();
while (c < '0' || c > '9') {
if (c == '-') f = -1;
c = getchar();
}
while (c >= '0' && c <= '9')
res = (res << 3) + (res << 1) + (c - '0'), c = getchar();
x = f * res;
}
void OUT(int x) {
if (x < 0) putchar('-'), x = -x;
if (x > 9) OUT(x / 10);
putchar(x % 10 + '0');
}
void print(int a, char c) { OUT(a), putchar(c); }
const int maxn = 10 + 2;
const int mod = 1e9 + 7;
int n, m;
char c[maxn][maxn];
int dp[maxn][maxn];
struct node {
int x, y;
node() {}
node(int _x, int _y) { x = _x, y = _y; }
};
int dx[] = {1, -1, 0, 0}, dy[] = {0, 0, 1, -1};
vector<node> g[maxn * maxn]; //记录每个连通块的点
int cnt;
queue<node> q;
// bfs主要操作
int bfs(int sx, int sy, int id, int tx, int ty) {
int mx = 0; // bfs1需要的
if (id != 0) mst(dp, -1); // bfs0不用初始化,bfs1需要初始化。
while (!q.empty()) q.pop();
q.push(node(sx, sy));
dp[sx][sy] = 0;
if (id == 2) q.push(node(tx, ty)), dp[tx][ty] = 0; //双起点的情况
while (!q.empty()) {
node now = q.front();
q.pop();
int x = now.x, y = now.y;
mx = max(mx, dp[x][y]);
if (id == 0) g[cnt].pb(node(x, y));
for (int i = 0; i < 4; i++) {
int nx = x + dx[i], ny = y + dy[i];
if (nx >= 1 && nx <= n && ny >= 1 && ny <= m && dp[nx][ny] == -1 &&
c[nx][ny] == '#') {
dp[nx][ny] = dp[x][y] + 1;
q.push(node(nx, ny));
}
}
}
return mx;
}
//找连通块数目
bool bfs0() {
bool f = true;
for (int i = 1; i <= n && f; i++) {
for (int j = 1; j <= m && f; j++) {
if (dp[i][j] == -1 && c[i][j] == '#') ++cnt, bfs(i, j, 0, 0, 0);
// if (cnt >= 3) f = false; //不可能。还省了很多bfs的复杂度
//也不知道为啥直接return false(甚至不能提前退出);就会出现问题emmm.
}
}
if (cnt >= 3) return false; //.直接返回f也可
return true; // cnt=1||2才返回
}
//从不同的起点开始bfs
int bfs1() {
int mx = 0, mi;
for (int i = 1; i <= cnt; i++) {
mi = 1e9;
for (auto j : g[i]) {
int tmp = bfs(j.x, j.y, 1, 0, 0);
mi = min(mi, tmp);
}
if (mi == 1e9) continue;
mx = max(mx, mi);
// dbg(mx);
}
return mx;
}
int bfs2() {
int mi = 1e9;
for (auto i : g[1]) {
for (auto j : g[1]) {
mi = min(mi, bfs(i.x, i.y, 2, j.x, j.y));
}
}
return mi;
}
void init() {
for (int i = 1; i <= cnt; i++) g[i].clear();
cnt = 0, mst(dp, -1); //注意一定要初始化0。
}
signed main() {
int T;
read(T);
int cas = 0;
while (T--) {
read(n), read(m);
for (int i = 1; i <= n; i++) scanf("%s", c[i] + 1);
// for (int i = 1; i <= n; i++) printf("%s\n", c[i] + 1);
init();
if (!bfs0())
printf("Case %d: %d\n", ++cas, -1); //, dbg(cnt);
else if (cnt == 2)
printf("Case %d: %d\n", ++cas, bfs1());
else
printf("Case %d: %d\n", ++cas, bfs2());
}
return 0;
}
/*
4
3 3
.#.
###
.#.
3 3
.#.
#.#
.#.
3 3
...
#.#
...
3 3
###
..#
#.#
*/