AcWing372 棋盘覆盖(匈牙利算法)

没见过这种题型,所以感觉很巧妙,因为要求不能够有两个方块占用同一个格子

所以可以想到将相邻的两个格子想成一条线,而一个格子是一个点。

这也就是最大匹配问题,如何将选出的边没有公共点,而边其实就是相邻的两个格子

这点比较朴素,但是之后要想到可以把相邻的点按照横纵坐标和的奇偶性看成两种不同的点

而所有的边就是两个不同点的连线,因此这是二分图的最大匹配问题,结合数据范围,考虑采用匈牙利算法

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> pll;
const int N=1e5;
pll match[200][200];
int st[200][200];
int g[200][200];
int dx[]={-1,0,1,0};
int dy[]={0,1,0,-1};
int n,t;
bool find(int x,int y){
    int i,j;
    for(i=0;i<4;i++){
        int a=x+dx[i];
        int b=y+dy[i];
        if(a&&a<=n&&b&&b<=n){
            if(st[a][b]||g[a][b])
            continue;
            st[a][b]=1;
            auto t=match[a][b];
            if(t.first==0||find(t.first,t.second)){
                match[a][b]={x,y};
                return true;
            }
        }
    }
    return false;
}
int main(){
    cin>>n>>t;
    int i,j;
    for(i=1;i<=t;i++){
        int x,y;
        cin>>x>>y;
        g[x][y]=1;
    }
    int res=0;
    for(i=1;i<=n;i++){
        for(j=1;j<=n;j++){
            if((j+i)%2&&!g[i][j]){
                memset(st,0,sizeof st);
                if(find(i,j))
                res++;
            }
        }
    }
    cout<<res<<endl;
}
View Code

 

posted @ 2020-06-30 20:23  朝暮不思  阅读(168)  评论(0编辑  收藏  举报