poj 2446解题报告
2013-08-27 14:32
274 查看
题目来源:http://poj.org/problem?id=2446
题目大意:
给你一个棋盘,让你用一些1*2的木块覆盖这个棋盘,但是棋盘上有些位置是有hole的,这些hole是不能被覆盖的。如果可以覆盖的话就输出YES,否则输出NO。
题目分析:
这道题很容易让人想起poj2411(也是一道很经典的题目),但是那道题是要求方案数目,这道题是求可否满足,是完全不同的,一开始感觉这道题数据不是很大,应该是一道搜索题,但是仔细一计算,发现是会超时的。。其实这是一道二分图匹配的题目。把hole占的位置去掉,剩下的分两组,建成二分图,怎么建图呢?其实可以这样分,把棋盘上任意一个当成是黑色的,然后他周围的四个都是白色的,这样一次往外延伸,最后把整个棋盘染成黑白相间的,这样同一颜色的方块遍当成是一组,组成二分图。
代码实现:
题目大意:
给你一个棋盘,让你用一些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; }
相关文章推荐
- POJ 2446解题报告
- poj1742 Coins 解题报告
- POJ 3076 Sudoku 解题报告(Dancing Link)
- POJ 1009不算解题报告的解题报告
- POJ 1458(最长公共子序列 动态规划) 解题报告
- poj 1469 COURSES 解题报告
- Poj Tree Grafting 解题报告 (左儿子右兄弟)
- POJ1094解题报告
- POJ 3264解题报告
- POJ 1077 解题报告
- POJ 1042 解题报告
- poj 2389 解题报告 大数乘法
- poj 1118 Lining Up 解题报告
- 【转】POJ试题分类 - 实时更新我所有的解题报告链接
- POJ 1195 解题报告
- 有向图的汇点 -- 兼 ACM PKU POJ 2186 ( Popular Cows ) 解题报告
- POJ 1146 解题报告
- poj 2176-Folding解题报告
- POJ-1840 Eqs 解题报告
- POJ 3468 线段树 解题报告