[Non] 棋盘上的马
棋盘上的马
大意
给一个棋盘,和其上的不能放置的位置,求最多能放多少个互不攻击的马。
思路
首先,棋盘上约束的问题,可以考虑使用二分图最大匹配。
二分图的特性是二分的图,分成两半,这个题,由于马的走法,故每次跳到的地方的行列之和的奇偶性都不同。
于是按行列和的奇偶性去构造一个二分图,把不能跳的地方也用边建出来,于是问题就转换为求二分图最大点独立集。
代码
#include<iostream>
#include<vector>
#include<cstring>
using namespace std;
const int MAXN = 500;
bool vis[MAXN], vail[MAXN][MAXN];
int mac[MAXN], n, m;
vector<int> g[MAXN];
int dx[] = {1, 2, 2, 1, -1, -2, -2, -1};
int dy[] = {2, 1, -1, -2, -2, -1, 1, 2};
int id(int i, int j){
return i * n + j;
}
bool dfs(int u){
for(int &v : g[u]){
if(!vis[v]){
vis[v] = true;
if(mac[v] == -1 || dfs(mac[v])){
mac[v] = u;
return true;
}
}
}
return false;
}
int hungary(int n){
int cnt = 0;
for(int i = 0;i < n;i ++){
for(int j = 0;j < n;j ++){
if(vail[i][j]) continue;
memset(vis, 0, sizeof(vis));
int pos = id(i, j);
if((i + j) % 2){
cnt += dfs(pos);
}
}
}
return cnt;
}
int main(){
cin >> n >> m;
memset(mac, -1, sizeof(mac));
for(int i = 1;i <= m;i ++){
int x, y; cin >> x >> y;
vail[x - 1][y - 1] = 1;
}
for(int i = 0;i < n;i ++){
for(int j = 0;j < n;j ++){
int pos = id(i, j);
if(vail[i][j]) continue;
for(int k = 0;k < 8;k ++){
int nx = i + dx[k];
int ny = j + dy[k];
if(nx < 0 || ny < 0 || nx >= n || ny >= n || vail[nx][ny]){
continue;
}
g[pos].push_back(id(nx, ny));
}
}
}
cout << n * n - m - hungary(n) << '\n';
return 0;
}
本文来自一名高中生,作者:To_Carpe_Diem

浙公网安备 33010602011771号