题意
给你一个n * n的矩阵,矩阵有#和.你现在能用一个1*2的矩阵去圈#,你圈的#必须是两个连在一起的,圈了就没有了,问你最多能圈多少次。
思路
最开始就想着bfs求每个连通块的数量。然后累加每个连通块数量/2,然后一直wa,然后师兄提出了一个样例
因为我们只能将这个1 * 2的矩阵上下左右平移所以我们对于这个例子我们只能圈1次,而不是2次。
所以我们现在的思路还是求出每个联通块,但是我们要知道一个#的坐标之和一定是奇数或者偶数,然后如果我们如果要配对的话一定是一个奇数匹配一个偶数,就如上面这个例子,坐标之和为奇数的只有一个,偶数有四个那么我们能匹配的数量就越是1,最终我们答案就是我们这个连通块每个#坐标值和的奇偶数的最小值。
代码
#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false);cin.tie(nullptr)
#define int long long
#define endl "\n"
#define xx first
#define yy second
using namespace std;
typedef pair<int, int> PII;
const int N = 100;
const int dx[] = {-1, 0, 1, 0};
const int dy[] = {0, -1, 0, 1};
int n, m, k, _, ans, tmp;
char g[N][N];
bool st[N][N];
int bfs(int x, int y)
{
st[x][y] = 1;
queue<PII>q;
q.push({x, y});
int c1 = 0, c2 = 0;
if((x+y) % 2 == 0) c2++;//本身的奇偶的情况也要算
else c1++;
while(!q.empty())
{
auto t = q.front();
q.pop();
for(int i = 0; i < 4; i ++)
{
int nx = t.xx + dx[i];
int ny = t.yy + dy[i];
if(st[nx][ny]) continue;
if(nx < 1 || nx > n || ny < 1 || ny > n || g[nx][ny] == '.') continue;
st[nx][ny] = 1;
if((nx+ny) % 2 == 0) c2++;//判断每一个的奇偶数的情况
else c1++;
q.push({nx, ny});
}
}
return min(c1, c2);
}
void solve()
{
cin >> n;
for(int i = 1; i <= n; i ++)
{
for(int j = 1; j <= n; j ++)
{
st[i][j] = 0;
cin >> g[i][j];
}
}
ans = 0;
for(int i = 1; i <= n; i ++)
{
for(int j = 1; j <= n; j ++)
{
if(g[i][j] == '#' && !st[i][j])
{
ans += bfs(i, j);
}
}
}
cout << ans << endl;
}
signed main()
{
IOS;
cin >> _;
for(int i = 1; i <= _; i ++)
{
cout << "Case " << i << ": ";
solve();
}
return 0;
}