算法
二分图+最小独立集
思路
在日字形内两点连边(1),必处于不同色格子(0)。为二分图。要互不相扰,求最大独立集。
核心
最大匹配
bool dfs(int x, int y) {
for (int i = 0; i < 8; i++) {
int nx = x + dx[i], ny = y + dy[i];
if (nx < 1 || ny < 1 || nx > n || ny > m || a[nx][ny]) continue;//范围判定
if (v[nx][ny]) continue;
v[nx][ny] = 1;
if (fx[nx][ny] == 0 || dfs(fx[nx][ny], fy[nx][ny])) {
fx[nx][ny] = x, fy[nx][ny] = y;
return true;
}
}
return false;
}
就加了个范围判定。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n, m, t, ans, fx[105][105], fy[105][105];
bool a[105][105], v[105][105];
const int dx[8] = {-2, -2, -1, -1, 1, 1, 2, 2};
const int dy[8] = {-1, 1, -2, 2, -2, 2, -1, 1};
bool dfs(int x, int y) {
for (int i = 0; i < 8; i++) {
int nx = x + dx[i], ny = y + dy[i];
if (nx < 1 || ny < 1 || nx > n || ny > m || a[nx][ny]) continue;
if (v[nx][ny]) continue;
v[nx][ny] = 1;
if (fx[nx][ny] == 0 || dfs(fx[nx][ny], fy[nx][ny])) {
fx[nx][ny] = x, fy[nx][ny] = y;
return true;
}
}
return false;
}
int main() {
cin >> n >> m >> t;
for (int i = 1; i <= t; i++) {
int x, y; cin >> x >> y;
a[x][y] = 1;
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (i + j & 1) continue;
if (a[i][j]) continue;
memset(v, 0, sizeof(v));
if (dfs(i, j)) ans++;
}
}
cout << n * m - t - ans << endl;//n*m个节点,但有t个不嫩放的不在二分图中,所以二分图节点只有n*m-t个节点。减ans为最大独立集。(基本操作)
}
作者:ruanmowen
链接:https://www.acwing.com/activity/content/code/content/284341/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。