ZOJ1516.Uncle Tom's Inherited Land——二分匹配,构图

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=516

http://blog.sina.com.cn/s/blog_7d3ee9f501015amd.html

题目描述:
你的老叔叔Tom 从他的老老叔叔那里继承过来一块土地。最初,这块土地是长方形的。然而,很久以前,他的老老叔叔决定把这块土地分成方形土地的网格。他将其中的一些方块挖成池塘,因为他喜欢打猎,所以他想把野鸭吸引到他的池塘里来。由于池塘挖得太多了,导致在土地里可能形成了一些不连通的小岛。
Tom 想卖掉这块土地,但当地政府对不动产的出售有相应的政策。你的叔叔被告知,依照他的老老叔叔的要求,这块土地只能以两块方块土地组成的长方形土地块起进行出售,而且,池塘是不许卖的。你的叔叔请你帮忙计算他可以出售的最大长方形土地块数目(没卖出的方块土地将被规划成休闲公园)。

就是一个矩形,求用1*2的白色块填充它,求最多能用的白色块

//C++0x 0   756
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
const int MAXN=110;
using namespace std;
int n,m,k;
int pic[MAXN][MAXN];
int d[4][2]={0,1,0,-1,1,0,-1,0};
int nx,ny;
int xs[MAXN][MAXN],ys[MAXN][MAXN];
vector<int> g[MAXN*MAXN];
int from[MAXN*MAXN],tot;
bool use[MAXN*MAXN];
bool match(int x){
    for(int i=0;i<g[x].size();++i){
        if(!use[g[x][i]]){
            use[g[x][i]]=true;
            if(from[g[x][i]]==-1||match(from[g[x][i]])){
                from[g[x][i]]=x;
                return true;
            }
        }
    }
    return false;
}
int hungary(){
    tot=0;
    memset(from,0xff,sizeof(from));
    for(int i=1;i<=nx;++i){
        memset(use,0,sizeof(use));
        if(match(i))
            tot++;
    }
    return tot;
}
void addedge(int x,int y){
    for(int i=0;i<4;++i){
        int xx=x+d[i][0];
        int yy=y+d[i][1];
        if(xx>=1&&xx<=n&&yy>=1&&yy<=m&&ys[xx][yy])
            g[xs[x][y]].push_back(ys[xx][yy]);
    }
}
int main()
{
//#ifndef ONLINE_JUDGE
//freopen("in.cpp","r",stdin);
//freopen("out.cpp","w",stdout);
//#endif // ONLINE_JUDGE
    int u,v;
    while(scanf("%d%d",&n,&m),n,m){
        memset(pic,0,sizeof(pic));
        memset(xs,0,sizeof(xs));
        memset(ys,0,sizeof(ys));
        scanf("%d",&k);
        while(k--){
            scanf("%d%d",&u,&v);
            pic[u][v]=1;
        }
        nx=ny=0;
        for(int i=1;i<=n;++i){
            for(int j=1;j<=m;++j){
                if(!pic[i][j]){
                    if((i+j)&1) xs[i][j]=++nx;
                    else ys[i][j]=++ny;
                }
            }
        }
        for(int i=1;i<=n;++i){
            for(int j=1;j<=m;++j){
                if(xs[i][j]){
                    g[xs[i][j]].clear();
                    addedge(i,j);
                }
            }
        }
        printf("%d\n",hungary());
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值