POJ-2226-Muddy Fields
http://poj.org/problem?id=2226
建图很巧妙,一块木板能覆盖一行或一列的土地,先按行来铺木块,再按列来铺木块
*.*. 按行1 0 2 0 按列 1 0 4 0
.*** 0 3 3 3 0 3 4 5
***. 4 4 4 0 2 3 4 0
..*. 0 0 5 0 0 0 4 0
对每个*的行和列连一条边,构成二分图,题目便转化为求最小点覆盖,即最大二分匹配
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
int n1,n2;
char map[1005][1005]; //数组开大点,不然会WA
int mapx[1005][1005],mapy[1005][1005];
int ma[1005][1005];
int result[1005],visit[1005];
int x,y;
int find(int a)
{
int i;
for(i=1;i<=y;i++)
{
if(!visit[i]&&ma[a][i])
{
visit[i]=1;
if(!result[i]||find(result[i]))
{
result[i]=a;
return 1;
}
}
}
return 0;
}
int main()
{
int i,j,ans;
while(scanf("%d%d",&n1,&n2)!=EOF)
{
for(i=0;i<n1;i++)
scanf("%s",map[i]);
memset(mapx,0,sizeof(mapx));
memset(mapy,0,sizeof(mapy));
x=0;
for(i=0;i<n1;i++)
for(j=0;j<n2;j++)
if(map[i][j]=='*')
{
++x;
while(j<n2&&map[i][j]=='*')
{
mapx[i][j]=x;
j++;
}
}
y=0;
for(j=0;j<n2;j++)
for(i=0;i<n1;i++)
if(map[i][j]=='*')
{
++y;
while(i<n1&&map[i][j]=='*')
{
mapy[i][j]=y;
i++;
}
}
for(i=0;i<n1;i++)
for(j=0;j<n2;j++)
ma[mapx[i][j]][mapy[i][j]]=1;
ans=0;
memset(result,0,sizeof(result));
for(i=1;i<=x;i++)
{
memset(visit,0,sizeof(visit));
ans+=find(i);
}
printf("%d\n",ans);
}
return 0;
}