//n*n的油田,有的有油,有的是水,
//问用最多能覆盖多少个1*2的格子
//对每一个有油的格子,如果其上下左右有油,那么在这两个点建边
//然后求最大匹配
#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
using namespace std ;
const int maxn = 610 ;
int id[maxn][maxn] ;
char map[maxn][maxn] ;
vector<int> vec[maxn*maxn] ;
int vis[maxn*maxn] ;
int match[maxn*maxn] ;
int dx[4] = {0 , 1 ,-1 ,0} ;
int dy[4] = {1 , 0 , 0 ,-1} ;
bool find(int u)
{
for(int i = 0 ;i < vec[u].size();i++)
{
int v = vec[u][i] ;
if(!vis[v])
{
vis[v] = 1 ;
if(match[v] == -1 || find(match[v]))
{
match[v] = u ;
return true ;
}
}
}
return false ;
}
int main()
{
int t ;
scanf("%d" , &t) ;
int cas = 0 ;
while(t--)
{
int n ;
int len = 0 ;
scanf("%d" , &n) ;
memset(match , -1 , sizeof(match)) ;
for(int i = 1;i <= n*n;i++)
vec[i].clear() ;
for(int i = 1;i <= n;i++)
{
scanf("%s", &map[i][1]) ;
for(int j = 1;j <= n;j++)
if(map[i][j] == '#')
id[i][j] = ++len ;
}
for(int i = 1;i <= n;i++)
for(int j = 1;j <= n;j++)
if(map[i][j] == '#')
for(int k = 0 ;k < 4;k++)
{
int nx = i + dx[k] ;
int ny = j + dy[k] ;
if(nx < 1 || nx > n || ny < 1 || ny > n)
continue ;
if(map[nx][ny] == '#')
{
vec[id[nx][ny]].push_back(id[i][j]) ;
vec[id[i][j]].push_back(id[nx][ny]) ;
}
}
int ans = 0 ;
for(int i = 1;i <= len;i++)
{
memset(vis , 0 , sizeof(vis)) ;
if(find(i))
ans++ ;
}
printf("Case %d: " , ++cas) ;
cout<<ans/2<<endl;
}
}
hdu4185Oil Skimming 二分匹配
最新推荐文章于 2018-11-08 19:54:04 发布