【算法复习】codevs1022 匈牙利算法
题目描述 Description
有一个N×M的单位方格中,其中有些方格是水塘,其他方格是陆地。如果要用1×2的矩阵区覆盖(覆盖过程不容许有任何部分重叠)这个陆地,那么最多可以覆盖多少陆地面积。
输入描述 Input Description
输入文件的第一行是两个整数N,M (1<=N,M<=100),第二行为一个整数K( K<=50),接下来的K行,每行两个整数X,Y表示K个水塘的行列位置。(1<=X<=N,1<=Y<=M)。
输出描述 Output Description
输出所覆盖的最大面积块(1×2面积算一块)。
样例输入 Sample Input
4 4
6
1 1
1 4
2 2
4 1
4 2
4 4
样例输出 Sample Output
4
【题解】普通二分图匹配,黑白染色
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<iostream> using namespace std; const int m1[4]={0,0,1,-1},m2[4]={1,-1,0,0}; int n,m,k,a[101][101],cnt[2],tag[101][101],c[5001][5001],all,used[5001],girl[5001]; inline bool find(int h){ for(int i=1;i<=cnt[1];i++) if(c[h][i]==true&&used[i]==false){ used[i]=true; if(girl[i]==0||find(girl[i])){ girl[i]=h; return true; } } return false; } int main(){ scanf("%d%d%d",&n,&m,&k); for(int i=1,x,y;i<=k;i++){ scanf("%d%d",&x,&y); a[x][y]=1; } for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(!a[i][j]){ cnt[(i+j)&1]++; tag[i][j]=cnt[(i+j)&1]; } for(int i=1;i<=n;i++) for(int j=1,x,y;j<=m;j++){ if((!a[i][j])&&(i+j)%2==0){ for(int k=0;k<4;k++){ x=i+m1[k];y=j+m2[k]; if(!(1<=x&&x<=n&&1<=y&&y<=m)) continue; if(!a[x][y]){ c[tag[i][j]][tag[x][y]]=1; } } } } for(int i=1;i<=cnt[0];i++){ memset(used,false,sizeof(used)); if(find(i)) all++; } cout<<all<<endl; return 0; }
当然,比赛的时候谁会去写这玩意啊
蜉蝣渴望着飞翔,尽管黄昏将至