您的位置:首页 > 其它

POJ-2446 Chessboard 最大匹配

2012-11-26 17:57 387 查看
  题目链接:http://poj.org/problem?id=2446

  昨天没有搞出来,今天汇编课想出来了,发现还是水水的,昨天估计是受到前面两题的影响,一直把思考方向搞错了= =||。

  题目要求用1*2的卡片覆盖整个区域,而且要恰好完全覆盖,不能有重叠。仔细发现,每个格子要么是被横着的1*2的卡片覆盖,要么是竖着的覆盖,而且每个只能和周围上下左右的四个格子同时覆盖,那么这里就可以抽象出每个格子和周围四个格子的匹配问题,就像国际象棋的黑白相间的格子一样。

  例如(0可放,-1不可放):

      0 -1 0            1 0 2      0 0 0

      0 0 0 ——————>    0 3 0      1 0 2

      0 0 -1            4 0 0      0 3 0

      0 0 0            0 5 0      4 0 5

     初始的棋盘           X集合 Y集合

  那么就是求X集合和Y集合的最大匹配,如果最大匹配是完备匹配,那么就是YES了,否则就是NO。

//STATUS:G++_AC_188MS_1660KB
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<map>
using namespace std;
#define LL long long
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
#define mem(a,b) memset(a,b,sizeof(a))
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
const int MAX=35,INF=0x3f3f3f3f;

int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};
int w[MAX*MAX>>1][MAX*MAX>>1],g[MAX][MAX],y[MAX*MAX],vis[MAX*MAX];
int n,m,k,coux,couy;

void getg()
{
int i,j,flag=0,k,ni,nj;
mem(w,0);
for(i=0;i<n;i++)
for(j=flag^=1;j<m;j+=2)
if(g[i][j]!=-1)g[i][j]=++couy;
flag=1;
for(i=0;i<n;i++){
for(j=flag^=1;j<m;j+=2){
if(g[i][j]!=-1){
++coux;
for(k=0;k<4;k++){
ni=i+dx[k],nj=j+dy[k];
if(ni>=0&&ni<n && nj>=0&&nj<m && g[ni][nj]!=-1){
w[coux][g[ni][nj]]=1;
}
}
}
}
}
}

int dfs(int u)
{
int v;
for(v=1;v<=couy;v++){
if(w[u][v] && !vis[v]){
vis[v]=1;
if(!y[v] || dfs(y[v])){
y[v]=u;
return 1;
}
}
}
return 0;
}

int main()
{
//  freopen("in.txt","r",stdin);
int i,j,a,b,ok;
while(~scanf("%d%d%d",&n,&m,&k))
{
mem(g,0);
mem(y,0);
coux=couy=0;
ok=1;
for(i=0;i<k;i++){
scanf("%d%d",&a,&b);
g[b-1][a-1]=-1;
}

if(!(k&1)){
getg();
if(coux==couy){
for(i=1;i<=coux;i++){
mem(vis,0);
if(!dfs(i)){
ok=0;
break;
}
}
}
else ok=0;
}
else ok=0;

printf("%s\n",ok?"YES":"NO");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: