Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 3483 | Accepted: 1299 |
Description
Input
Output
Sample Input
4 4 *.*. .*** ***. ..*.
Sample Output
4
Hint
Source
把行里面连在一起的坑连起来视为一个点,即一块横木板,编上序号,Sample则转化为:
1 0 2 0
0 3 3 3
4 4 4 0
0 0 5 0
把这些序号加入X集合,再按列做一次则为:
1 0 4 0
0 3 4 5
2 3 4 0
0 0 4 0
同样加入Y集合,一个坑只能被横着的或者被竖着的木板盖住,将原图的坑的也标上不同的序号,一共九个坑
1 . 2 .
. 3 4 5
67 8 .
. . 9 .
比如7号坑可以被横着的4号木板和竖着的3号木板盖住,把每个点的对应的横木板(4)和竖木板(3)中间连一条边的话,则问题转化为 找尽量少的边把这些点都盖住,根据xxxxx定理便是求最大匹配数
#include<stdio.h>
#include<string.h>
int r,c;
char str[51][51];
int x[51][51],y[51][51];
int mat[1255][1255];
int link[1255];
bool usedif[1255];
int numb,numa;
bool can(int t)
{
for(int i=1;i<=numb;i++)
if(usedif[i]==0&&mat[t][i]==1)
{
usedif[i]=1;
if(link[i]==-1||can(link[i]))
{
link[i]=t;
return true;
}
}
return false;
}
int MaxMatch()
{
int num=0;
memset(link,-1,sizeof(link));
for(int i=1;i<=numa;i++)
{
memset(usedif,0,sizeof(usedif));
if(can(i)) num++;
}
return num;
}
int main()
{
while(scanf("%d%d",&r,&c)!=EOF)
{
for(int i=0;i<r;i++) scanf("%s",str[i]);
numa=0;
for(int i=0;i<r;i++)
for(int j=0;j<c;j++)
{
if(j==0)
{
if(str[i][j]=='*') x[i][j]=++numa;
}
else
{
if(str[i][j]=='*')
{
if(str[i][j]==str[i][j-1]) x[i][j]=numa;
else x[i][j]=++numa;
}
}
}
numb=0;
for(int j=0;j<c;j++)
for(int i=0;i<r;i++)
{
if(i==0)
{
if(str[i][j]=='*') y[i][j]=++numb;
}
else
{
if(str[i][j]=='*')
{
if(str[i][j]==str[i-1][j]) y[i][j]=numb;
else y[i][j]=++numb;
}
}
}
memset(mat,0,sizeof(mat));
for(int i=0;i<r;i++)
for(int j=0;j<c;j++)
{
mat[x[i][j]][y[i][j]]=1;
}
printf("%d/n",MaxMatch());
}
return 0;
}