Code[VS] 1022 覆盖 题解
题目描述 Description
有一个N×M的单位方格中,其中有些方格是水塘,其他方格是陆地。如果要用1×2的矩阵区覆盖(覆盖过程不容许有任何部分重叠)这个陆地,那么最多可以覆盖多少陆地面积。
输入描述 Input Description
输入文件的第一行是两个整数N,M (1<=N,M<=100),第二行为一个整数K( K<=50),接下来的K行,每行两个整数X,Y表示K个水塘的行列位置。(1<=X<=N,1<=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
(完)