题目传送门
题意解析:题目给了一张图,上面有的地方不能放马(中国象棋里的),问最多能放几只马。
……..跟bzoj3175几乎一模一样,包括数据范围,所以详情请见bzoj3175
代码,好像也一样:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define rep(i,a,n) for (int i=a;i<=n;i++)
#define per(i,a,n) for (int i=a;i>=n;i--)
#define Clear(a,x) memset(a,x,sizeof(a))
#define ll long long
#define INF 2000000000
#define eps 1e-8
using namespace std;
int read(){
int x=0,f=1;
char ch=getchar();
while (ch<'0'||ch>'9') f=ch=='-'?-1:f,ch=getchar();
while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*f;
}
const int maxn=205,maxm=maxn*maxn;
const int dx[8]={-1,-2,-2,-1,1,2,2,1},dy[8]={-2,-1,1,2,2,1,-1,-2};
int n,m,len,ans,sum;
int map[maxn][maxn],match[maxm];
int vet[maxm<<4],Next[maxm<<4],head[maxm];
bool flag[maxm];
void add(int u,int v){
vet[++len]=v;
Next[len]=head[u];
head[u]=len;
}
int calc(int x,int y){
return (x-1)*m+y;
}
bool dfs(int u){
for (int e=head[u];e;e=Next[e]){
int v=vet[e];
if (flag[v]) continue;
flag[v]=1;
int t=match[v];
match[v]=u;
if (t==-1||dfs(t))
return true;
match[v]=t;
}
return false;
}
int main(){
n=read(),m=read();
rep(i,1,n)
rep(j,1,m) map[i][j]=read(),sum+=(map[i][j]==0);
rep(i,1,n)
rep(j,1,m)
rep(k,0,7){
if (map[i][j]==1) break;
int xx=dx[k]+i,yy=dy[k]+j;
if (xx<1||xx>n||yy<1||yy>m||map[xx][yy]==1) continue;
int u=calc(i,j),v=calc(xx,yy);
add(u,v);
}
Clear(match,-1);
rep(i,1,n)
rep(j,1,m) if (map[i][j]==0){
Clear(flag,0);
flag[calc(i,j)]=1;
ans+=dfs(calc(i,j));
}
printf("%d\n",sum-ans/2);
return 0;
}