hdu1045 Fire Net(二分图匹配)

题目大意:

一个n*n的方形城市,我们现在要在这座城市中放置几栋房子。

这些房子两两之间必须满足以下条件之一:

1.不在同一行且不在同一列。

2.在同一行或同一列,但是中间有障碍物阻隔(图中的'X')

思路:

比较类似于八皇后问题,如果没有障碍物,这道题直接将行列分开,通过交点建边就可以解决。

处理障碍物的方法:先行后列,先列后行。分别遍历一遍,在同一行/列且中间没有‘X'的交点看作二分图中同一个顶点(重赋点),最后在遍历每一个'.'建边即可。

#include 
#include 
#include 
#include 
#include 
using namespace std;
#define N 12
#define INF 0x3f3f3f3f
struct node
{
	int v, next;
}a[N*N*N];
int head[N], used[N], girl[N], c[N][N], l[N][N];
int n, m, cnt;
char map[N][N];
void add(int u, int v)
{
	a[cnt].v = v;
	a[cnt].next = head[u];
	head[u] = cnt++;
}
int find(int x)
{
	int i;
	
	for(i = head[x]; i != -1; i = a[i].next)
	{
		int v = a[i].v;
		
		if(used[v] == -1)
		{
			used[v] = 1;
			if(girl[v] == -1 || find(girl[v]))
			{
				girl[v] = x;
				return 1;
			}
		}
	}
	return 0;                                                 
}
int main()
{
	while(scanf("%d", &n) && n)
	{
		int i, j, ans = 0, res = 0, m;
		
		for(i = 0; i < n; i++)
			scanf("%s", map[i]);
		for(i = 0; i < n; i++)
		{
			res++;
			for(j = 0; j < n; j++)
			{
				if(map[i][j] == 'X')
					res++;
				else
					c[i][j] = res;
			}
		}
		m = res;
		res = 0;
		for(j = 0; j < n; j++)
		{
			res++;
			for(i = 0; i < n; i++)
			{
				if(map[i][j] == 'X')
					res++;
				else
					l[i][j] = res;
			}
		}
		cnt = 0;
		memset(head, -1, sizeof(head));
		for(i = 0; i < n; i++)
			for(j = 0; j < n; j++)
				if(map[i][j] == '.')
					add(c[i][j], l[i][j]);
		memset(girl, -1, sizeof(girl));
		for(i = 1; i <= m; i++)
		{
			memset(used, -1, sizeof(used));
			if(find(i))
				ans++;
		}
		printf("%d\n", ans);
	}
	return 0;
}


你可能感兴趣的:(acm)