题意 :有R×C方阵,'*'铺表示洼地,需要上宽度为1的木板,长度不限,只能横放或竖放.木板可以重叠,但不能覆盖'.'求覆盖所有'*'洼地所用的最少木板数.
构图: 将所有横向且连续(一个或以上)的'*'看成一个点并对其进行编号,所有的编号都为集合X内的编号总数为uN。同样地,将所有的竖向且连续(一个或以上)的'*'看成一个点并对其编号,所有的编号都为集合Y内的编号总数为vN.然后用二分匹配,最小覆盖点等于最大匹配。
疑问的是:在二分匹配中代码部分vU和uN交换为什么就WA???搞不明白。。。从X集合向Y用dfs和Y向X用dfs理应是一样的哈.
#include <iostream>
#include<cstring>
using namespace std;
int map[2255][2555];
int f[5509];
int mat[5500];
int vN,uN;
int dfs(int u)
{
int i,t;
for(i=1;i<=vN;i++)
{
if(!f[i]&&map[u][i])
{
f[i]=1;
t=mat[i];
if(!t||dfs(t))
{
mat[i]=u;
return 1;
}
}
}
return 0;
}
int match()
{
int i;
int sum=0;
memset(mat,0,sizeof(mat));
for(i=1;i<=uN;i++)
{
memset(f,0,sizeof(f));
if(dfs(i))
{
sum++;
}
}
return sum;
}
int main()
{
int i, j, n, m;
cin>>n>>m;
int cx[500][500],cy[500][500];
char map1[55][55];
memset(map, 0, sizeof(map));
for(i = 1; i <= n; i++)
for(j = 1; j <= m; j++)
cin>>map1[i][j];
vN = uN = 0;
for(i = 1; i <= n; i++)
for(j = 1; j <= m; j++)
if(map1[i][j] == '*')
{
uN++;
while(j <= m && map1 [i][j] == '*')
{
cx[i][j] = uN;
j++;
}
}
for(j = 1; j <= m; j++)
for(i = 1; i <= n; i++)
if(map1 [i][j] == '*')
{
vN++;
while(i <= n && map1 [i][j] == '*')
{
cy[i][j] = vN;
i++;
}
}
for(i = 1; i <= n; i++)
for(j = 1; j <= m; j++)
if(map1 [i][j] == '*')
{
map[cx[i][j]][cy[i][j]] = 1;
}
cout<<match()<<endl;
return 0;
}