codevs 1022 覆盖(匈牙利算法)


codevs 1022 覆盖(匈牙利算法)

  Time Limit: 1 Sec
  Memory Limit: 128 MB

Description

   有一个N×M的单位方格中,其中有些方格是水塘,其他方格是陆地。如果要用1×2的矩阵区覆盖(覆盖过程不容许有任何部分重叠)这个陆地,那么最多可以覆盖多少陆地面积。
p1
 

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/
  本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

猜你喜欢

转载自www.cnblogs.com/shaokele/p/9915138.html