您的位置:首页 > 其它

poj 2446解题报告

2013-08-27 14:32 274 查看
题目来源:http://poj.org/problem?id=2446

题目大意:

给你一个棋盘,让你用一些1*2的木块覆盖这个棋盘,但是棋盘上有些位置是有hole的,这些hole是不能被覆盖的。如果可以覆盖的话就输出YES,否则输出NO。

题目分析:

这道题很容易让人想起poj2411(也是一道很经典的题目),但是那道题是要求方案数目,这道题是求可否满足,是完全不同的,一开始感觉这道题数据不是很大,应该是一道搜索题,但是仔细一计算,发现是会超时的。。其实这是一道二分图匹配的题目。把hole占的位置去掉,剩下的分两组,建成二分图,怎么建图呢?其实可以这样分,把棋盘上任意一个当成是黑色的,然后他周围的四个都是白色的,这样一次往外延伸,最后把整个棋盘染成黑白相间的,这样同一颜色的方块遍当成是一组,组成二分图。

代码实现:

#include <stdio.h>
#include <string.h>
#include <iostream>
#define MAX 1500
using namespace std;

int n,m,k,match;
int adjl[MAX][MAX];
int mat[MAX];
bool used[MAX];
int map[MAX][MAX];

FILE *fi,*fo;
int ink1;
void input()
{
int x,y;
scanf("%d%d%d",&n,&m,&k);
memset(mat,0,sizeof(mat));
for(int i=1; i<n; i++)
adjl[i][0] = 0;
int ink = 0;
memset(map,0,sizeof(map));
for(int i=1; i<=k; i++)
{
scanf("%d%d",&x,&y);
map[y][x] = -1;
}
for(int i=1; i<=n; i++)
{
for(int j=1; j<=m; j++)
{
if(map[i][j] != -1)
{
ink++;
map[i][j] = ink;
}
}
}
ink1=0;
for(int i=1; i<=n; i++)
{
for(int j=1; j<=m; j++)
{
if(map[i][j] != -1)
{
ink1++;
if(i-1>=1 && map[i-1][j] != -1)
{
adjl[ink1][++adjl[ink1][0]] = map[i-1][j];
}
if(j-1>=1 && map[i][j-1] != -1)
{
adjl[ink1][++adjl[ink1][0]] = map[i][j-1];
}
if(j+1<=m && map[i][j+1] != -1)
{
adjl[ink1][++adjl[ink1][0]] = map[i][j+1];
}
if(i+1<=n && map[i+1][j] != -1)
{
adjl[ink1][++adjl[ink1][0]] = map[i+1][j];
}
}
}
}
match=0;
}

bool crosspath(int k)
{
for (int i=1; i<=adjl[k][0]; i++)
{
int j=adjl[k][i];
if (!used[j])
{
used[j]=true;
if (mat[j]==0 || crosspath(mat[j]))
{
mat[j]=k;
return true;
}
}
}
return false;
}

void hungary()
{
for (long i=1; i<=ink1; i++)
{
memset(used,false,sizeof(used));
if (crosspath(i))
{match++;}
}
}

int main()
{
input();
if((n*m-k)%2 == 1)
printf("NO\n");
else
{
hungary();
if(match == (n*m-k))
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: