这是个最大匹配的经典题,个人推荐做一做,对建模的理解会更深刻。
总的来说,就是以每个横向的连续污点构成一个X点,以每个纵向的连续污点构成一个Y点,若横向与纵向同时覆盖了一个点,则连接XY。
构图完毕,然后用匈牙利算法。
#include <cstdio>
#include <cstring>
const int maxr = 60;
const int maxn = 1000;
int un,vn,r,c;
char mp[maxr][maxr];
int g[maxn][maxn],a[maxr][maxr],b[maxr][maxr];
int link[maxn];
bool vis[maxn];
bool dfs(int u)
{
for (int v = 0; v < vn; v++)
{
if (g[u][v] && !vis[v])
{
vis[v] = 1;
if (link[v]==-1 || dfs(link[v]))
{
link[v] = u;
return 1;
}
}
}
return 0;
}
int KM()
{
int res = 0;
memset(link, -1, sizeof(link));
memset(vis, 0, sizeof(vis));
for (int u = 0; u < un; u++)
{
if (dfs(u))
{
res++;
memset(vis, 0, sizeof(vis));
}
}
return res;
}
int main()
{
while (scanf("%d%d",&r,&c)==2)
{
memset(g,0,sizeof(g));
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
for (int i=0;i<r;i++) scanf("%s",mp[i]);
un=0;
for (int i=0;i<r;i++)
for (int j=0;j<c;j++)
{
if (mp[i][j]=='*')
{
a[i][j]=un;
if (mp[i][j+1]!='*') un++;
}
}
vn=0;
for (int j=0;j<c;j++)
for (int i=0;i<r;i++)
{
if (mp[i][j]=='*')
{
b[i][j]=vn;
if (mp[i+1][j]!='*') vn++;
}
}
for (int i=0;i<r;i++)
for (int j=0;j<c;j++)
if (mp[i][j]=='*')
g[a[i][j]][b[i][j]]=1;
int ans=KM();
printf("%d\n",ans);
}
return 0;
}