这题的关键在于建图,这题当中,因为要求木板覆盖泥坑,但又不能覆盖草,所以不能简单的行和列对应建图,我们要对行中泥坑进行编号,连一起的编同样的号,同样的对列中连一起的泥坑进行编号,如果行列编号的一块泥坑连一起,便为这两个编号建立边,这样对其进行匈牙利算法求最大匹配,就是最小覆盖点,就是答案。
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#define maxn 505
#define mem(a) memset(a, 0, sizeof(a))
using namespace std;
char maps[maxn][maxn];
bool map[maxn][maxn], vis[maxn];
int lk[maxn], numw[maxn][maxn], n, m, w, h;
bool dfs(int a)
{
int i;
for(i = 0;i <= h;i++)
{
if(!vis[i]&&map[a][i])
{
vis[i] = 1;
if(lk[i] == -1||dfs(lk[i]))
{
lk[i] = a;
return true;
}
}
}
return false;
}
int res()
{
int i;
int ress = 0;
memset(lk, -1, sizeof(lk));
for(i = 0;i <= w;i++)
{
mem(vis);
if(dfs(i))
ress++;
}
return ress;
}
int main(int argc, char *argv[])
{
int eagenum, i, j, ans;
while(scanf("%d%d%*c", &n, &m) != EOF)
{
mem(map);
mem(maps);
w = -1;
h = -1;
for(i = 0;i < n;i++)
{
for(j = 0;j < m;j++)
{
scanf("%c", &maps[i][j]);
}
scanf("%*c");
}
for(i = 0;i < n;i++)
{
for(j = 0;j < m;j++)
{
if(j == 0&&maps[i][j] == '*')
numw[i][j] = ++w;
else if(maps[i][j] == '*'&&maps[i][j - 1] == '*')
numw[i][j] = w;
else if(maps[i][j] == '*'&&maps[i][j - 1] != '*')
numw[i][j] = ++w;
}
}
for(i = 0;i < m;i++)
{
for(j = 0;j < n;j++)
{
if(j == 0&&maps[j][i] == '*')
map[numw[j][i]][++h] = 1;
else if(maps[j][i] == '*'&&maps[j - 1][i] == '*')
map[numw[j][i]][h] = 1;
else if(maps[j][i] == '*'&&maps[j - 1][i] != '*')
map[numw[j][i]][++h] = 1;
}
}
ans = res();
printf("%d\n", ans);
}
return 0;
}