题目描述:
听说最近两斑点的奶牛最受欢迎,约翰立即购进了一批两斑点牛。
不幸的是,时尚潮流往往变化很快,当前最受欢迎的牛变成了一斑点牛。
约翰希望通过给每头奶牛涂色,使得它们身上的两个斑点能够合为一个斑点,让它们能够更加时尚。
牛皮可用一个 $ N \times M $ 的字符矩阵来表示,如下所示:
1 2 3 4 5 6
| ................ ..XXXX....XXX... ...XXXX....XX... .XXXX......XXX.. ........XXXXX... .........XXX....
|
其中, $ X $ 表示斑点部分。
如果两个 $ X $ 在垂直或水平方向上相邻(对角相邻不算在内),则它们属于同一个斑点,由此看出上图中恰好有两个斑点。
约翰牛群里所有的牛都有两个斑点。
约翰希望通过使用油漆给奶牛尽可能少的区域内涂色,将两个斑点合为一个。
在上面的例子中,他只需要给三个 .. 区域内涂色即可(新涂色区域用 ∗∗ 表示):
1 2 3 4 5 6
| ................ ..XXXX....XXX... ...XXXX*...XX... .XXXX..**..XXX.. ........XXXXX... .........XXX....
|
请帮助约翰确定,为了使两个斑点合为一个,他需要涂色区域的最少数量。
输入格式
第一行包含两个整数 $ N $ 和 $ M $ 。
接下来 $ N $ 行,每行包含一个长度为 $ M $ 的由 $ X $ 和 .. 构成的字符串,用来表示描述牛皮图案的字符矩阵。
输出格式
输出需要涂色区域的最少数量。
数据范围
$ 1\le N, M \le 50 $
输入样例:
1 2 3 4 5 6 7
| 6 16 ................ ..XXXX....XXX... ...XXXX....XX... .XXXX......XXX.. ........XXXXX... .........XXX....
|
输出样例:
题解:
因为数据范围比较小,所以可以将每块连通块中 $ X $ 的坐标记下来,然后直接暴力枚举求得最短距离。
(bfs 的时候,注意队列里面是没有重复的,每个元素只进一次队列,所以每次加入后就要打上标记)
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
| using namespace std; using namespace FAST_IO; const ll mod = 1e9 + 7; const int INF = 0x3f3f3f3f; const ll INF_LL = 0x3f3f3f3f3f3f3f3f; const double eps = 1e-5; const int maxn = 1e2 + 10; const int maxm = 1e2 + 10; int t, n, m, k; char g[maxn][maxn]; vector<pair<int, int>> a, b; int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1}; void bfs(int x, int y, int flag) { queue<pair<int, int>> q; q.push({x, y}); g[x][y] = '.'; while (!q.empty()) { auto out = q.front(); q.pop(); if (flag) { b.push_back(out); } else { a.push_back(out); } for (int i = 0; i < 4; i++) { int newx = dx[i] + out.first; int newy = dy[i] + out.second; if (newx < 0 || newx >= n || newy < 0 || newy >= m || g[newx][newy] == '.') continue; q.push({newx, newy}); g[newx][newy] = '.'; } } } int main() {
#ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); #endif read(n, m); for (int i = 0; i < n; i++) { scanf("%s", g[i]); } int cnt = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { if (g[i][j] == 'X') { if (cnt) { bfs(i, j, cnt); } else { bfs(i, j, cnt); } cnt++; } } } int ans = INF; for (auto x : a) { for (auto y : b) { ans = min(ans, abs(x.first - y.first) + abs(x.second - y.second) - 1); } } cout << ans << endl; return 0; }
|