在一个N行M列的二维网格里,有些格子是空地(用字符‘.’表示),有些格子是障碍物(用字符‘#’表示)。每个空地格子都有一只虫子,虫子不会移动。FJ打算用最少的炸弹把所有的虫子消灭。FJ每次可以选择在一个空地格子(不妨假设是格子a)放置一个炸弹,这个炸弹爆炸后,格子a的虫子会被消灭,假设有另一个空地格子b,如果空地格子b同时满足如下两个条件,那么空地b格子的虫子也会被该炸弹消灭:
1.格子a和格子b在同一行或者在同一列。
2.格子a和格子b之间没有障碍物格子。
有趣的是,任意两个不同的空地格子都有且只有一条由空地格子构成的路径,即所有空地格子构成一棵树形结构。注意:炸弹并不能毁灭障碍物!
第一行,两个整数,n和m。1 <= n, m<=50。
接下来是n行m列的二维网格。
输出最少的炸弹数。
输入1:
3 4
#…
…##
#.##
输入2:
3 7
.#.#.#.
…
.#.#.#.
输出1:
2
输出2:
4
30%的数据满足空地格子数量小于20
样例解释1:
#.B.
.B##
#.##
样例解释2:
.#.#.#.
B.B.B.B
.#.#.#.
字符B表示放置炸弹
#include
#include
#include
using namespace std;
#define N 55
char a[N][N];
int b1[N][N], b2[N][N], vi[N * N];
struct {
int l, r, u, d;
}c[N][N];
int last[N * N], nxt[N * N * 2], to[N * N * 2], len = 0;
int f[N * N][3];
void add(int x, int y) {
to[++len] = y;
nxt[len] = last[x];
last[x] = len;
}
void dfs(int k, int fa) {
vi[k] = 1;
f[k][2] = 0, f[k][0] = 1;
int sum = 0;
for(int i = last[k]; i; i = nxt[i]) if(to[i] != fa) {
int x = to[i];
dfs(x, k);
f[k][2] += min(f[x][0], f[x][1]);
sum += min(min(f[x][0], f[x][1]), f[x][2]);
}
f[k][0] += sum;
f[k][1] = f[k][0];
for(int i = last[k]; i; i = nxt[i]) if(to[i] != fa) {
int x = to[i];
f[k][1] = min(f[k][1], sum - min(min(f[x][0], f[x][1]), f[x][2]) + f[x][0]);
}
}
int main() {
int n, m, i, j;
scanf("%d%d\n", &n, &m);
for(i = 1; i <= n; i++) scanf("%s\n", a[i] + 1);
for(i = 1; i <= n; i++) {
for(j = 1; j <= m; j++) if(a[i][j] == '.') {
if(j > 1 && a[i][j - 1] == '.') c[i][j].l = c[i][j - 1].l + 1; else c[i][j].l = 1;
}
for(j = m; j; j--) if(a[i][j] == '.') {
if(j < m && a[i][j + 1] == '.') c[i][j].r = c[i][j + 1].r + 1; else c[i][j].r = 1;
}
}
for(j = 1; j <= m; j++) {
for(i = 1; i <= n; i++) if(a[i][j] == '.') {
if(i > 1 && a[i - 1][j] == '.') c[i][j].u = c[i - 1][j].u + 1; else c[i][j].u = 1;
}
for(i = n; i; i--) if(a[i][j] == '.') {
if(i < n && a[i + 1][j] == '.') c[i][j].d = c[i + 1][j].d + 1; else c[i][j].d = 1;
}
}
int tot = 0;
for(i = 1; i <= n; i++) {
for(j = 1; j <= m; j++) if(a[i][j] == '.') {
int u = b1[i][j - c[i][j].l + 1];
if(!u) u = b1[i][j - c[i][j].l + 1] = ++tot;
int v = b2[j][i - c[i][j].u + 1];
if(!v) v = b2[j][i - c[i][j].u + 1] = ++tot;
add(u, v), add(v, u);
}
}
dfs(1, 0);
printf("%d", min(min(f[1][0], f[1][1]), f[1][2]));
return 0;
}