题目大意:黑白矩阵,每次可以选择一个四联通块染色,求最少操作次数
题解:将目标状态里相同颜色的联通块缩点,枚举起点,生成树里的最大节点深度就是需要的次数了
如果最大深度是白色的话记得-1
我的收获:bfs树
#include <queue>
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
const int MAXN = 54;
const int dx[] = { 1, 0, -1, 0 };
const int dy[] = { 0, 1, 0, -1 };
char color[MAXN * MAXN];
vector<int> e[MAXN * MAXN];
char buf[MAXN][MAXN];
int tag[MAXN][MAXN];
void floodfill(int x, int y, int z, char c) {
if (buf[x][y] != c) {
return;
}
buf[x][y] = '\0';
tag[x][y] = z;
for (int i = 0; i < 4; ++i) {
floodfill(x + dx[i], y + dy[i], z, c);
}
}
int gao(int n, int s) {
int ret = -1;
queue<int> q;
vector<int> d(n, -1);
d[s] = 0;
q.push(s);
while (!q.empty()) {
s = q.front();
q.pop();
ret=d[s];
if (color[s] == 'W') ret--;
for (vector<int>::iterator it = e[s].begin(); it != e[s].end(); ++it) {
if (d[*it] == -1) {
d[*it] = d[s] + 1;
q.push(*it);
}
}
}
return ret;
}
int main() {
int n, r, c, ans;
scanf("%d%d", &r, &c);
for (int i = 1; i <= r; ++i) {
scanf("%s", buf[i] + 1);
}
n = 0;
for (int i = 1; i <= r; ++i) {
for (int j = 1; j <= c; ++j) {
if (buf[i][j] != '\0') {
color[n] = buf[i][j];
floodfill(i, j, n, buf[i][j]);
++n;
}
}
}
for (int i = 1; i <= r; ++i) {
for (int j = 1; j <= c; ++j) {
for (int k = 0; k < 4; ++k) {
int x = i + dx[k];
int y = j + dy[k];
if (1 <= x && x <= r && 1 <= y && y <= c && tag[i][j] != tag[x][y]) {
e[tag[i][j]].push_back(tag[x][y]);
}
}
}
}
for (int i = 0; i < n; ++i) {//去重
sort(e[i].begin(), e[i].end());
e[i].erase(unique(e[i].begin(), e[i].end()), e[i].end());
}
ans = n;
for (int i = 0; i < n; ++i) {
ans = min(ans, gao(n, i));
}
printf("%d\n", ans + 1);
return 0;
}