标签:hdu 1045 fire net 二分匹配 匈牙利算法

4 .X.. .... XX.. .... 2 XX .X 3 .X. X.X .X. 3 ... .XX .XX 4 .... .... .... .... 0
5 1 5 2 4
题意:给定一个最大4*4的方形地图,里面有墙(X)和空地(.)。在每个空地上可以放大炮,但两个大炮如果在同一行或同一列并且之间没有墙阻隔的话,会互相攻击,所以不能同时存在。问最多能放多少个大炮。
题解:二分匹配。建图的话就是同一行连续的‘.‘看做为一个节点,为A集合,同一列也一样,为B集合。
A,B中只要有交点就加边。
ACcode:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <queue>
#include <cmath>
#include <string>
#define N 101010
#define MaxN 10100
#define INF 1<<29
using namespace std;
int uN,vN;
int linker[20];
char mp[6][6];
bool used[20];
int mp1[6][6],mp2[6][6],maze[6][6];
int n,m;
bool dfs(int u) {
int v;
for(v=1; v<=vN; v++)
if(maze[u][v]&&!used[v]) {
used[v]=true;
if(linker[v]==-1||dfs(linker[v])) {
linker[v]=u;
return true;
}
}
return false;
}
int hungary() {
int res=0;
int u;
memset(linker,-1,sizeof(linker));
for(u=1; u<=uN; u++) {
memset(used,0,sizeof(used));
if(dfs(u)) res++;
}
return res;
}
int main() {
//freopen("in.txt","r",stdin);
while(~scanf("%d",&n)&&n) {
for(int i=0; i<n; i++) {
scanf("%s",mp[i]);
}
int l1=1,l2=1;
memset(mp1,0,sizeof mp1);
memset(mp2,0,sizeof mp2);
for(int i=0; i<n; i++) {
for(int j=0; j<n; j++) {
if(mp1[i][j])continue;
if(mp[i][j]=='X') {
mp1[i][j]=0;
continue;
}
while(mp[i][j]=='.'&&j<n)mp1[i][j]=l1,j++;
l1++;
}
for(int j=0; j<n; j++) {
if(mp2[j][i])continue;
if(mp[j][i]=='X') {
mp2[j][i]=0;
continue;
}
while(mp[j][i]=='.'&&j<n)mp2[j][i]=l2,j++;
l2++;
}
}
memset(maze,0,sizeof maze);
for(int i=0; i<n; i++) {
for(int j=0; j<n; j++) {
if(mp[i][j]!='X') {
maze[mp1[i][j]][mp2[i][j]]=1;
}
}
}
uN=l1-1;
vN=l2-1;
int ans=hungary();
printf("%d\n",ans);
}
return 0;
}标签:hdu 1045 fire net 二分匹配 匈牙利算法
原文地址:http://blog.csdn.net/acm_baihuzi/article/details/45727889