Battle ships HDU - 5093
题目大意:
给出一个n行m列的图,*代表海域,o代表冰水,#代表冰山,要想在海域中放置船,保证船与船之间不能相互看到,之间只要有山就不能看到,问最多能放多少船。
分析:
这道题其实是使用二分图最大匹配来做,重点就在建图上,先一行一行的看,每到一行计数x1++,如果碰到#,x1也++,这样每个*就对应了一个号,然后再一列一列到看同理,每到一列y1++,碰到#,y1++,当是\ *给它赋值当前到号。这样一个*点就有了两个值,恰好可以建二分图,然后用匈牙利算法即可
code:
#include <cstdio>
#include <cstring>
#include <algorithm>
#define maxn 55
using namespace std;
int mp[maxn * 55][maxn * 55];
char str[maxn][maxn];
int used[maxn * 55];
int link[maxn * 55];
int x[maxn][maxn];
int y[maxn][maxn];
int n, m;
int x1, y1;
void init(){
memset(mp, 0, sizeof(mp));
memset(x, 0, sizeof(x));
memset(y, 0, sizeof(y));
}
void input(){
scanf("%d%d", &n, &m);
for(int i = 0; i < n; ++i)
scanf("%s", str[i]);
}
void creat_x(){
x1 = 1;
for(int i = 0; i < n; ++i){
for(int j = 0; j < m; ++j){
if(str[i][j] == '*')
x[i][j] = x1;
if(str[i][j] == '#')
x1++;
}
x1++;
}
return ;
}
void creat_y(){
y1 = 1;
for(int j = 0; j < m; ++j){
for(int i = 0; i < n; ++i){
if(str[i][j] == '*')
y[i][j] = y1;
if(str[i][j] == '#')
y1++;
}
y1++;
}
return ;
}
void getmap(){
for(int i = 0; i < n; ++i){
for(int j = 0; j < m; ++j)
if(str[i][j] == '*')
mp[x[i][j]][y[i][j]] = 1;
}
return ;
}
bool dfs(int x){
for(int i = 1; i < y1; ++i){
if(mp[x][i] && !used[i]){
used[i] = 1;
if(link[i] == -1 || dfs(link[i])){
link[i] = x;
return true;
}
}
}
return false;
}
int hungary(){
int ans = 0;
memset(link, -1, sizeof(link));
for(int j = 1; j < x1; ++j){
memset(used, 0, sizeof(used));
if(dfs(j))
ans++;
}
return ans;
}
int main (){
int T;
scanf("%d", &T);
while(T--){
init();
input();
creat_x();
creat_y();
getmap();
int sum = hungary();
printf("%d\n", sum);
}
return 0;
}