题目
给定一个 N*M 的棋盘,有一些格子禁止放棋子。
问棋盘上最多能放多少个不能互相攻击的骑士(国际象棋的“骑士”,类似于中国象棋的“马”,按照“日”字攻击,但没有中国象棋“别马腿”的规则)。
输入格式
第一行包含三个整数N,M,T,其中T表示禁止放置的格子的数量。
接下来T行每行包含两个整数x和y,表示位于第x行第y列的格子禁止放置,行列数从1开始。
输出格式
输出一个整数表示结果。
数据范围
1≤N,M≤100
思路
把坐标和为奇数的点视为棋盘的白色位置,偶数为黑色位置,跑一边二分图最大匹配即可
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef unsigned long long ull;
#define x first
#define y second
const int N=110;
int n,m,k;
pii match[N][N];
bool g[N][N],st[N][N];
int dx[8]={-2,-1,1,2,2,1,-1,-2};
int dy[8]={1,2,2,1,-1,-2,-2,-1};
bool find(int x,int y)
{
for(int i=0;i<8;i++)
{
int a=x+dx[i],b=y+dy[i];
if(a<1||a>n||b<1||b>m) continue;
if(g[a][b]) continue;
if(st[a][b]) continue;
st[a][b]=true;
pii t=match[a][b];
if(t.x==0||find(t.x,t.y))
{
match[a][b]={x,y};
return true;
}
}
return false;
}
int main()
{
//freopen("test.in","r",stdin);//设置 cin scanf 这些输入流都从 test.in中读取
//freopen("test.out","w",stdout);//设置 cout printf 这些输出流都输出到 test.out里面去
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>n>>m>>k;
for(int i=0;i<k;i++)
{
int x,y;
cin>>x>>y;
g[x][y]=true;
}
int res=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if((i+j)%2 || g[i][j]) continue;
memset(st,0,sizeof st);
if(find(i,j)) res ++;
}
}
cout<<n*m-k-res<<endl;
return 0;
}