機智建圖法。行爲一個集合裏的點,不能互相攻擊的行算兩個;列爲另一個集合裏的點。這樣做一個二分圖匹配,一個行就不能跟多個列匹配,避免出現互相攻擊的狀況,相當於做了一次縮點。
#include<iostream>
#include<cstdio>
#include<string.h>
#include<algorithm>
using namespace std;
int n,cntx,cnty,girl[100],h[100][100],l[100][100];
bool line[100][100],used[100];
char mapp[100][100];
bool finds(int x)
{
//cout<<"yes"<<endl;
//cout<<"cntx="<<cntx<<" cnty="<<cnty<<endl;
for (int j=0; j<cnty; j++)
{
//cout<<"x="<<x<<" j="<<j<<endl;
if (line[x][j] && !used[j])
{
used[j]=1;
if (girl[j]==-1 || finds(girl[j]))
{
girl[j]=x;
//cout<<"x="<<x<<" j="<<j<<endl;
return true;
}
}
}
return false;
}
int main()
{
while (~scanf("%d",&n) && n)
{
for (int i=1; i<=n; i++)
{
for (int j=1; j<=n; j++)
{
char ch; cin>>ch; mapp[i][j]=ch;
}
}
cntx=0; cnty=0;
for (int i=1; i<=n; i++)
{
for (int j=1; j<=n; j++)
{
if (mapp[i][j]=='.')
{
if (j==0) h[i][j]=cntx++;
else if (mapp[i][j-1]=='.') h[i][j]=h[i][j-1];
else h[i][j]=cntx++;
if (i==0) l[i][j]=cnty++;
else if (mapp[i-1][j]=='.') l[i][j]=l[i-1][j];
else l[i][j]=cnty++;
}
}
}
memset(line,false,sizeof(line));
for (int i=1; i<=n; i++)
{
for (int j=1; j<=n; j++)
{
if (mapp[i][j]=='.')
line[h[i][j]][l[i][j]]=true;
}
}
int all=0;
memset(girl,-1,sizeof(girl));
for (int i=0; i<cntx; i++)
{
memset(used,false,sizeof(used));
//cout<<"i="<<i<<endl;
//cout<<"!cntx="<<cntx<<" cnty="<<cnty<<endl;
if (finds(i)) all+=1;
}
cout<<all<<endl;
}
return 0;
}