http://blog.acmj1991.com/?p=754
题意:用木板将'*'覆盖,同一行或同一列的'*'可以用一块木板覆盖,'.'不能被覆盖。问最少用多少块木板可以把全部的'*'覆盖?
思路:最小点集覆盖,以前做过一个类似的题目,只不过那是能炸一整行或者一整列。其实这一题也是差不多,只不过是把不像连的‘*’分开,分成两行或者两列。求出最大匹配即使答案
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
#define maxN 4000
struct node{
int v,next;
}po[4*maxN];
int num,head[maxN],vis[maxN],pre[maxN];
int ro[60][60],co[60][60];
void init()
{
memset(head,-1,sizeof(head));
memset(vis,false,sizeof(vis));
memset(pre,-1,sizeof(pre));
memset(ro,0,sizeof(ro));
memset(co,0,sizeof(co));
num=0;
}
void add(int u,int v)
{
po[num].v=v;
po[num].next=head[u],head[u]=num++;
}
int mat(int u)
{
for(int i=head[u];i!=-1;i=po[i].next){
int v=po[i].v;
if(!vis[v]){
vis[v]=true;
if(pre[v]==-1||mat(pre[v]))
{
pre[v]=u;
return true;
}
}
}
return false;
}
int main()
{
freopen("2.txt","r",stdin);
int col,row;
while(~scanf("%d%d",&row,&col))
{
init();
char map[60][60];
int k=1,u,v;
for(int i=0;i<row;i++)
scanf("%s",map[i]);
for(int i=1;i<=row;i++)
for(int j=1;j<=col;j++)
if(map[i-1][j-1]=='*')
{
ro[i][j]=ro[i][j-1]>0?ro[i][j-1]:k;
co[i][j]=co[i-1][j]>0?co[i-1][j]:k;
add(ro[i][j],co[i][j]);
k++;
}
int sum=0;
for(int i=1;i<k;i++){
memset(vis,false,sizeof(vis));
if(mat(i))sum++;
}
printf("%d\n",sum);
}
}