codevs 1022 覆盖(匈牙利算法)
codevs 1022 覆盖(匈牙利算法)##
Time Limit: 1 Sec
Memory Limit: 128 MBDescription###
有一个N×M的单位方格中,其中有些方格是水塘,其他方格是陆地。如果要用1×2的矩阵区覆盖(覆盖过程不容许有任何部分重叠)这个陆地,那么最多可以覆盖多少陆地面积。
Input###
输入文件的第一行是两个整数N,M (1<=N,M<=100),第二行为一个整数K( K<=50),接下来的K行,每行两个整数X,Y表示K个水塘的行列位置。(1<=X<=N,1<=Y<=M)。
Output###
输出所覆盖的最大面积块(1×2面积算一块)。
Sample Input###
4 4
6
1 1
1 4
2 2
4 1
4 2
4 4
Sample Output###
4
HINT
题目地址:codevs 1022 覆盖
题目大意: 题目很简洁了:)
题解:
棋盘黑白染色一下
黑色块白色块二分图匹配
每个黑块都只能和上下左右四个白块匹配
匈牙利跑一边就好了
极限 \(O(N^4)\) 然而显然跑不到
AC代码
#include <cstdio>
#include <cstring>
using namespace std;
const int N=105;
const int dx[4]={0,0,1,-1};
const int dy[4]={1,-1,0,0};
int n,m,K,Ans;
bool mark[N][N],used[N][N];
struct note{
int x,y;
}res[N][N];
bool find(int x,int y){
for(int i=0;i<4;i++){
int nx=x+dx[i];
int ny=y+dy[i];
if(1<=nx && nx<=n && 1<=ny && ny<=m && !mark[nx][ny]){
if(!used[nx][ny]){
used[nx][ny]=1;
if(!res[nx][ny].x || find(res[nx][ny].x,res[nx][ny].y)){
res[nx][ny]=(note){x,y};
return 1;
}
}
}
}
return 0;
}
int main(){
scanf("%d%d",&n,&m);
scanf("%d",&K);
while(K--){
int x,y;
scanf("%d%d",&x,&y);
mark[x][y]=1;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(!mark[i][j] && (i&1)==(j&1)){
memset(used,0,sizeof(used));
if(find(i,j))
Ans++;
}
printf("%d\n",Ans);
return 0;
}
作者:skl_win
出处:https://www.cnblogs.com/shaokele/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。