很好的一道题目。
题意:给定一个 M * N 大小的方格,地图有3中方格,墙、草地、空地。他的老板希望Robert能在地图中放置尽可能多的机器人。每个机器人可以向四个方向开火,激光可以穿透草地,但不能穿透墙壁。(http://www.cnblogs.com/g0feng/archive/2012/11/10/2763771.html)
求出最大可以放置的机器人数。
思路:
建图方式:矩阵横竖块建二分图,将问题转化为最大匹配问题。
这题是《图论算法理论、实现及应用》书中的例题,有详细的分析P361

1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 // Accepted 1654 C++ 50ms 6840K 6 #define MAXN 51 7 int xx, yy, x[MAXN*MAXN], y[MAXN*MAXN], xs[MAXN][MAXN], ys[MAXN][MAXN]; 8 char Graph[MAXN][MAXN]; 9 int vis[MAXN*MAXN]; 10 bool map[MAXN*MAXN][MAXN*MAXN]; 11 int row, col; 12 bool dfs( int u ) 13 { 14 int v; 15 for( v = 1; v <= yy; v++ ) 16 { 17 if( map[u][v] && !vis[v] ) 18 { 19 vis[v] = 1; 20 if( !y[v] || dfs( y[v] ) ) 21 { 22 x[u] = v; 23 y[v] = u; 24 return true; 25 } 26 } 27 } 28 return false; 29 } 30 void MaxMatch() 31 { 32 int u, ans = 0; 33 memset( x, 0, sizeof(x) ); 34 memset( y, 0, sizeof(y) ); 35 for( u = 1; u <= xx; u++ ) 36 { 37 if( !x[u] ) 38 { 39 memset( vis, 0, sizeof(vis) ); 40 if( dfs( u ) )ans++; 41 } 42 } 43 printf( "%d\n", ans ); 44 } 45 int main() 46 { 47 int cas, i, j, k, tot, flag; 48 scanf( "%d", &cas ); 49 for( k = 1; k <= cas; k++ ) 50 { 51 memset( xs, 0, sizeof(xs) ); 52 memset( ys, 0, sizeof(ys) ); 53 scanf( "%d%d", &row, &col ); 54 for( i = 0; i < row; i++ ) 55 scanf( "%s", Graph[i] ); 56 tot = 0; 57 for( i = 0; i < row; i++ ) 58 { 59 flag = 0; 60 for( j = 0; j < col; j++ ) 61 { 62 if( Graph[i][j] == 'o' ) 63 { 64 if( !flag )tot++; 65 xs[i][j] = tot; flag = 1; 66 } 67 else if( Graph[i][j] == '#' ) 68 flag = 0; 69 } 70 } 71 xx = tot; 72 tot = 0; 73 for( j = 0; j < col; j++ ) 74 { 75 flag = 0; 76 for( i = 0; i < row; i++ ) 77 { 78 if( Graph[i][j] == 'o' ) 79 { 80 if( !flag )tot++; 81 ys[i][j] = tot; flag = 1; 82 } 83 else if( Graph[i][j] == '#' ) 84 flag = 0; 85 } 86 } 87 yy = tot; 88 memset( map, 0, sizeof(map) ); 89 for( i = 0; i < row; i++ ) 90 for( j = 0; j < col; j++ ) 91 if( xs[i][j] )map[xs[i][j]][ys[i][j]] = 1; 92 printf( "Case :%d\n", k ); 93 MaxMatch(); 94 } 95 }