这道题是最小点覆盖的题,用最少的木板将泥地覆盖。我们建图时将横的线段看成二分图的X点,
将竖线段看成Y点。将每个横线段和竖线段编号,编号之后将有交点的横线段和竖线段连一条边,
求出最大匹配。 最小点覆盖 = 最大匹配。
/*Accepted 2440 KB 16 ms C++ 2186 B 2012-07-28 16:18:28*/ #include<cstdio> #include<cstring> #include<cstdlib> const int MAXN = 55; int xM[MAXN * MAXN / 2], yM[MAXN * MAXN / 2]; bool g[MAXN * MAXN / 2][MAXN * MAXN / 2]; int R, C; char map[MAXN][MAXN]; bool chk[MAXN * MAXN / 2]; int vN, uN; int xr[MAXN][MAXN], yc[MAXN][MAXN]; bool SearchPath(int u) { int v; for(v = 1; v <= vN; v ++) { if(g[u][v] && !chk[v]) { chk[v] = true; if( yM[v] == -1 || SearchPath(yM[v])) { yM[v] = u, xM[u] = v; return true; } } } return false; } int MaxMatch() { int u, ret = 0; memset( xM, -1, sizeof xM); memset( yM, -1, sizeof yM); for( u = 1; u <= uN; u ++) { if( xM[u] == -1) { memset( chk, false, sizeof chk); if(SearchPath(u)) ret ++; } } return ret; } void ReadGragh() { vN = 1, uN = 1; memset( xr, 0, sizeof xr); memset( yc, 0, sizeof yc); memset( g, false, sizeof g); for( int i = 0; i < R; i ++) { scanf( "%s", map[i]); } for( int i = 0; i < R; i ++) { for( int j = 0; j < C; j ++) { if( map[i][j] == '*') { xr[i][j] = uN; while( map[i][j] == '*') { xr[i][j] = uN; j ++; } uN ++; } } } for( int j = 0; j < C; j ++) { for( int i = 0; i < R; i ++) { if( map[i][j] == '*') { yc[i][j] = vN; while( map[i][j] == '*') { yc[i][j] = vN; i ++; } vN ++; } } } for( int i = 0; i < R; i ++) for( int j = 0; j < C; j ++) { if(map[i][j] == '*') { g[xr[i][j]][yc[i][j]] = true; } } } int main() { while( scanf( "%d%d", &R, &C) == 2) { ReadGragh(); printf( "%d\n", MaxMatch()); } return 0; }