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;
}