[bzoj-4808]马 题解

题目传送门
题意解析:题目给了一张图,上面有的地方不能放马(中国象棋里的),问最多能放几只马。


……..跟bzoj3175几乎一模一样,包括数据范围,所以详情请见bzoj3175
代码,好像也一样:

#include
#include
#include
#include
#include
#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;
}

你可能感兴趣的:(bzoj,二分图匹配)