Code[VS] 1022 覆盖 题解

Code[VS] 1022 覆盖 题解

Hungary Algorithm

题目传送门:Code[VS] 1022

题目描述 Description

有一个N×M的单位方格中,其中有些方格是水塘,其他方格是陆地。如果要用1×2的矩阵区覆盖(覆盖过程不容许有任何部分重叠)这个陆地,那么最多可以覆盖多少陆地面积。

输入描述 Input Description

输入文件的第一行是两个整数NM  (1<=NM<=100),第二行为一个整数K( K<=50),接下来的K行,每行两个整数X,Y表示K个水塘的行列位置。(1<=X<=N1<=Y<=M)。

输出描述 Output Description

输出所覆盖的最大面积块(1×2面积算一块)。

样例输入 Sample Input

4 4

6

1 1

1 4

2 2

4 1

4 2

4 4

样例输出 Sample Output

4

____________________________________分割线_____________________________________

分析:

将矩形的每一块分为 0 , 1 两个集合,相邻的两块属于不同的集合,如下图:

这时,这个问题就转化为一个典型的二分图匹配,可以使用Hungary Algorithm 解决。

代码:

 1 #include "cstdio"
 2 #include "cstring"
 3 #include "algorithm"
 4
 5 using namespace std ;
 6 const int maxN = 210 ;
 7 const int INF = 2147483647 ;
 8
 9 bool wat[ maxN ][ maxN ] , map[ maxN ][ maxN ] , used[ maxN ][ maxN ] ;
10
11 int N , M , k , ans , px , py ;
12
13 int from[ maxN ][ maxN ][ 2 ] ;
14
15 int _1[ 5 ] = { 0 , 1 , -1 , 0 , 0 } , _2[ 5 ] = { 0 , 0 , 0 , 1 , -1 } ;//方向
16
17 bool find ( int x , int y )
18 {
19     int px , py ;
20     for(int i=1 ; i<=4 ; ++i )
21     {
22         px = x + _1[i] ,py = y + _2[i];
23         if( px<=0 || px>N || py<=0 || py>M || wat[ px ][ py ] ) continue ;
24         if ( !wat[ px ][ py ] && !used[ px ][ py ] && !map[ px ][ py ])
25         {
26             used[ px ][ py ] = true ;
27             if( ( !from[ px ][ py ][ 0 ] ) || (find( from[ px ][ py ][ 0 ] , from[ px ][ py ][ 1 ] ) ) )
28             {
29                 from[ px ][ py ][ 0 ] = x ;
30                 from[ px ][ py ][ 1 ] = y ;
31                 return true ;
32             }
33         }
34     }
35     return false ;
36 }
37 int main()
38 {
39     scanf( "%d%d%d" , &N , &M , &k ) ;
40     for(int i=1 ; i<=k ; ++i )
41     {
42         int _x , _y ;
43         scanf( "%d%d" , &_x , &_y ) ;
44         wat[ _x ][ _y ] = true ;
45     }
46     for(int i=1 ; i<=N ; ++i )
47         for(int j=1 ; j<=M ; ++j )
48             if((i % 2 && j % 2) || (i%2==0 && j%2==0))map[ i][ j ] = 1 ;
49     for(int i=1 ; i<=N ; ++i )
50     {
51         for(int j=1 ; j<=M ; ++j )
52         {
53             if( !wat[ i ][ j ] && map[ i ][ j ] )
54             {
55                 memset ( used, 0 , sizeof ( used ) ) ;
56                 if ( find ( i , j ) ) ans++ ;
57             }
58         }
59     }
60     printf( "%d" , ans ) ;
61     return 0 ;
62 }

2016-09-16 15:46:24

(完)

时间: 2024-07-29 22:52:54

Code[VS] 1022 覆盖 题解的相关文章

Code[VS]1690 开关灯 题解

Code[VS]1690 开关灯 题解  时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description: YYX家门前的街上有N(2<=N<=100000)盏路灯,在晚上六点之前,这些路灯全是关着的,六点之后,会有M(2<=m<=100000)个人陆续按下开关,这些开关可以改变从第i盏灯到第j盏灯的状态,现在YYX想知道,从第x盏灯到第y盏灯中有多少是亮着的(1<=i,j,x,y<=N) 输入描述 Input

Code[VS] 2152 滑雪题解

Code[VS] 2152 滑雪题解 题目描述 Description trs喜欢滑雪.他来到了一个滑雪场,这个滑雪场是一个矩形,为了简便,我们用r行c列的矩阵来表示每块地形.为了得到更快的速度,滑行的路线必须向下倾斜.例如样例中的那个矩形,可以从某个点滑向上下左右四个相邻的点之一.例如24-17-16-1,其实25-24-23…3-2-1更长,事实上这是最长的一条. 输入描述 Input Description 输入文件 第1行: 两个数字r,c(1<=r,c<=100),表示矩阵的行列.第

codevs 1022 覆盖

题目链接:http://codevs.cn/problem/1022/ 题解: 匈牙利稍作改动,用邻接矩阵存储,以{横坐标和纵坐标都为奇数或横坐标和纵坐标都为偶数的点}为一个子集,其余的点为另一个子集,每次枚举4个方向进行深搜 1 #include<cstdio> 2 #include<cstring> 3 #define MAXN 110 4 int n,m,k,edge[MAXN][MAXN][2],ans; 5 bool used[MAXN][MAXN],map[MAXN][

Code[VS] 2370 LCA 题解

Code[VS] 2370 小机房的树 题解 LCA 题目描述 Description 小机房有棵焕狗种的树,树上有N个节点,节点标号为0到N-1,有两只虫子名叫飘狗和大吉狗,分居在两个不同的节点上.有一天,他们想爬到一个节点上去搞基,但是作为两只虫子,他们不想花费太多精力.已知从某个节点爬到其父亲节点要花费 c 的能量(从父亲节点爬到此节点也相同),他们想找出一条花费精力最短的路,以使得搞基的时候精力旺盛,他们找到你要你设计一个程序来找到这条路,要求你告诉他们最少需要花费多少精力 输入描述 I

【CODEVS】1022 覆盖

[算法]二分图匹配(最大流) [题解]对i+j进行奇偶染色,就可以保证相邻两格异色. 然后就是二分图了,对相邻格子连边跑最大流即可. #include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn=110,maxN=10100,inf=0x3f3f3f3f; struct edge{int from,v,flow;}e[300010]; int n,m,

bzoj 3225: [Sdoi2008] 立方体覆盖 题解

[原题] 3225: [Sdoi2008]立方体覆盖 Time Limit: 2 Sec  Memory Limit: 128 MB Submit: 51  Solved: 36 [Submit][Status] Description A君近日为准备省队选拔.特意进行了数据结构的专项训练.训练过程中就遇到了"矩形面积并"这道经典问题.即:给出N个各边与坐标轴平行(垂直)的矩形,求矩形覆盖的面积之和. A君按纵坐标建立线段树后按横坐标扫描计算.轻易AC了这道题,时间复杂度为O(Nlog

【基础练习】【贪心】codevs1214 线段覆盖题解

题目:已知数轴上0<N<10000条线段.每条线段按照端点Ai和Bi(Ai<>Bi,i=1..N)定义.端点坐标在(-999,999)内,坐标为整数.有些线段可能相交.编程实现删除最少数目的线段,使得余下的任意两条线段不相交. codevs和洛谷数据范围不同 改一下常量maxn即可 思路是很简单的贪心 //codevs1214 线段覆盖 贪心 //先排序,扫描一遍,每次保留右端点最小的线段,重叠的delete,画一张图即可证明 #include<cstdio> #inc

【codevs】1022覆盖(匈牙利算法)

嗯,先上题目描述... 此题接近裸的匈牙利算法,将陆地和其四周是陆地的点连一条边,这样就有了一个无向图. 接着就是从第一个点出发枚举未被标记的点,标记与其对应的另一个点(因为是1*2的长方形). 开了一个四维数组e[x1][y1][x2][y2],若为零代表点(x1,y1)与(x2,y2)不连通. match[x1][y1][1]放与点(x1,y1)配对的另一个点的x,match[x1][y1][2]放与点(x1,y1)配对点的y. 还有就是更改的时候记得双向更改,因为是无向图啊. 然后就跑df

LOJ6354 &amp; 洛谷4366:[Code+#4]最短路——题解

https://loj.ac/problem/6354 https://www.luogu.org/problemnew/show/P4366 题面见上面. 这题很妙,且可能是我傻,感觉这题不太好想. 前45pts很好骗就不说了. 朴素的建法是O(n^2+m)的,一个点都过不了. 然而事实上一个从x->y权值为w的边是可以被其他边取代的,我们可以把x拆成二进制,一位一位的修改最终到达y,此时经过的权值显然也是w. 也就是说,对于一个点x,我们只需要让他和x*2^k连边即可,这样就优化为O(nlo