把每一列中相邻的 . 缩为一个点 作为二分图的左边
把每一行中相邻的 . 缩为一个点 作为二分图的右边
然后求最大匹配即可
这题用匈牙利足够了。。。然而。。我用了hk。。。有点大材小用的感觉///
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <cmath>
#include <algorithm>
#define mem(a, b) memset(a, b, sizeof(a))
using namespace std;
const int maxn = , INF = 0x7fffffff;
int dx[maxn], dy[maxn], cx[maxn], cy[maxn], used[maxn];
int row[][], col[][];
int nx, ny, dis;
vector<int> G[];
char str[][];
int n;
int bfs()
{
queue<int> Q;
dis = INF;
mem(dx, -);
mem(dy, -);
for(int i=; i<=nx; i++)
{
if(cx[i] == -)
{
Q.push(i);
dx[i] = ;
}
}
while(!Q.empty())
{
int u = Q.front(); Q.pop();
if(dx[u] > dis) break;
for(int v=; v<G[u].size(); v++)
{
int i = G[u][v];
if(dy[i] == -)
{
dy[i] = dx[u] + ;
if(cy[i] == -) dis = dy[i];
else
{
dx[cy[i]] = dy[i] + ;
Q.push(cy[i]);
}
}
}
}
return dis != INF;
} int dfs(int u)
{
for(int v=; v<G[u].size(); v++)
{
int i = G[u][v];
if(!used[i] && dy[i] == dx[u] + )
{
used[i] = ;
if(cy[i] != - && dis == dy[i]) continue;
if(cy[i] == - || dfs(cy[i]))
{
cy[i] = u;
cx[u] = i;
return ;
}
}
}
return ;
} int hk()
{
int res = ;
mem(cx, -);
mem(cy, -);
while(bfs())
{
mem(used, );
for(int i=; i<=nx; i++)
{
if(cx[i] == - && dfs(i)) res++;
}
}
return res;
} int main()
{
while(cin>> n && n)
{ for(int i=; i<; i++) G[i].clear();
mem(row, -);
mem(col, -);
nx = ny = ;
for(int i=; i<n; i++)
{
cin>> str[i];
}
for(int i=; i<n; i++)
{
for(int j=; j<n; j++)
{
if(str[i][j] == '.' && row[i][j] == -)
{
for(int k=j; str[i][k]=='.' && k<n; k++)
row[i][k] = nx;
nx++;
}
if(str[j][i] == '.' && col[j][i] == -)
{
for(int k=j; str[k][i]=='.' && k<n; k++)
col[k][i] = ny;
ny++;
}
}
}
nx -= , ny -= ;
for(int i=; i<n; i++)
for(int j=; j<n; j++)
if(str[i][j] == '.')
G[row[i][j]].push_back(nx + col[i][j]), G[nx + col[i][j]].push_back(row[i][j]); cout<< hk() <<endl; } return ;
}
搜索写法:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int maxn = , INF = 0xfffffff;
typedef long long LL;
char str[maxn][maxn];
int vis[maxn][maxn];
int n, minn;
int check(int x,int y)
{
for(int i=x-; i>=; --i)
{
if(vis[i][y])
return ;
if(str[i][y] == 'X')
break;
}
for(int i=y-; i>=; --i)
{
if(vis[x][i])
return ;
if(str[x][i] == 'X')
break;
}
return ;
} void dfs(int inx, int k)
{
if(inx == n*n)
{
minn = max(k, minn);
return;
} int x = inx / n;
int y = inx % n;
if(str[x][y] == '.' && check(x,y))
{
vis[x][y] = ;
dfs(inx+, k+);
vis[x][y] = ;
}
dfs(inx+, k);
} int main()
{
while(cin>>n && n)
{
minn = -INF;
mem(vis,);
mem(str,);
for(int i=;i<n;i++)
cin>>str[i];
dfs(,);
cout<<minn<<endl; } return ;
}