题目链接:http://poj.org/problem?id=3020
题意:每个 ‘*’都需要一个1*2的东西覆盖,问最少需要多少个1*2的东西来覆盖这些‘*’
和Oil Skimming的题解几乎一样
#include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> #include<queue> using namespace std; #define N 660 #define INF 0xfffffff int dir[4][2] = {{1,0},{-1,0},{0,1},{0,-1} }; int G[N][N], a[N][N], cnt, vis[N], used[N];///a[i][j]代表这个位置#的编号从1开始; char maps[N][N]; bool Find(int u) { for(int i=1; i<cnt; i++) { if(!vis[i] && G[u][i]) { vis[i] = 1; if(!used[i] || Find(used[i])) { used[i] = u; return true; } } } return false; } int main() { int T, m, n; scanf("%d", &T); while(T--) { scanf("%d%d", &m, &n); cnt=1; memset(used, 0, sizeof(used)); memset(G, 0, sizeof(G)); memset(a, 0, sizeof(a)); memset(maps, 0, sizeof(maps)); for(int i=0; i<m; i++) { scanf("%s", maps[i]); for(int j=0; j<n; j++) { if(maps[i][j] == '*') a[i][j] = cnt++; } } for(int i=0; i<m; i++) { for(int j=0; j<n; j++) { if(maps[i][j]=='*') for(int k=0; k<4; k++)/// 上下左右建立关系; { int x = i+dir[k][0]; int y = j+dir[k][1]; if(x>=0 && y>=0 && x<m && y<n && maps[x][y]=='*') { int p=a[x][y]; int q=a[i][j]; G[p][q] = G[q][p] = 1;///建图; } } } } int ans = 0; for(int i=1; i<cnt; i++) { memset(vis, 0, sizeof(vis)); if(Find(i)) ans++; } printf("%d ", cnt-1-ans/2); } return 0; }