3041的加强版
这道题由于草地不能被木板覆盖,需要多处理一下
由于木板只能水平或垂直放,做两次处理,第一次把可以水平放置且不连续的木板编号,第二次把可以垂直放置且不连续的木板编号
将木板看成点,泥地看成边,一个泥点对应一条边,这样就转化成了二分图,求最小的点将所有的边覆盖即可,最小点覆盖=最大匹配数
代码:
#include<iostream>
using namespace std;
#define MAX 1005
int link[MAX],u[MAX],w[MAX][MAX],a[MAX][MAX],b[MAX][MAX];
char map[55][55];
int nx,ny;
int dfs(int t)
{
for(int i=1;i<=ny;i++)
{
if(!u[i]&&w[t][i])
{
u[i]=1;
if(link[i]==-1||dfs(link[i]))
{
link[i]=t;
return 1;
}
}
}
return 0;
}
int hungary()
{
int i,num=0;
memset(link,-1,sizeof(link));
for(i=1;i<=nx;i++)
{
memset(u,0,sizeof(u));
num+=dfs(i);
}
return num;
}
int main()
{
int r,c,i,j;
nx=ny=0;
scanf("%d%d",&r,&c);
getchar();
for(i=1;i<=r;i++)
{
for(j=1;j<=c;j++)
{
scanf("%c",&map[i][j]);
}
getchar();
}
for(i=1;i<=r;i++)
{
for(j=1;j<=c;j++)
{
if(map[i][j]=='*')
{
if(map[i][j-1]=='*')
a[i][j]=a[i][j-1];
else
a[i][j]=++nx;
}
}
}
for(i=1;i<=r;i++)
{
for(j=1;j<=c;j++)
{
if(map[i][j]=='*')
{
if(map[i-1][j]=='*')
b[i][j]=b[i-1][j];
else
b[i][j]=++ny;
w[a[i][j]][b[i][j]]=1;
}
}
}
printf("%d\n",hungary());
return 0;
}