Uva12549机器人警卫----二分图最大匹配

题意:

在一个Y行X列的网格里有空地(.),重要位置(*)和障碍物(#),用最少的机器人看守所有重要位置,每个机器人要放在一个格子里,面朝上下左右4个方向之一。机器人会发出激光,一直射到障碍物为止,沿途都是看守范围。

思路:

每个点就是把x,y连在一起,选取最少点覆盖所有的x,y,那么就是个二分图匹配,左边是x,右边是y。有障碍物,所以需要拆点,重新赋值行和列,每碰见一个障碍物,就将后面的所有东西移动到下一行,这样就不会有障碍物了。

#include <cstdio>
#include <queue>
#include <vector>
#include <cstring>
#include <algorithm>
#define fi first
#define se second
#define pii pair<int,int>
using namespace std;
const int INF = 0x3f3f3f3f;
typedef long long LL;
const int maxn = 100+5;

int row, col;
int book[maxn][maxn], G[maxn][maxn];
pii Gt[maxn][maxn];

int cy[maxn];
bool visy[maxn];
bool dfs(int u){
	for(int i = 0; i <= col; ++i){
		if(!visy[i]&&G[u][i]){
			visy[i] = 1;
			if(cy[i] == -1||dfs(cy[i])){
				cy[i] = u;
				return true;
			}
		}
	}
	return false;
}

int Maxmatch(){
	memset(cy, -1, sizeof(cy));
	int ans = 0;
	for(int i = 0; i <= row; ++i){
		memset(visy, 0, sizeof(visy));
		if(dfs(i)) ++ans;
	}	
	return ans;
}

int main()
{
	freopen("in.txt","r",stdin);
	int T, h, w, blocks, pots; scanf("%d",&T);
	while(T--){
		memset(book, 0, sizeof(book));
		memset(G, 0, sizeof(G));
		scanf("%d%d",&h,&w);
		scanf("%d",&pots);  // 重要的点
		for(int i = 0; i < pots; ++i){
			int x,y; scanf("%d%d",&x,&y);
			book[x-1][y-1] = 1;
		}
		scanf("%d",&blocks);  // 障碍数
		for(int i = 0; i < blocks; ++i){
			int x,y; scanf("%d%d",&x,&y);
			book[x-1][y-1] = 2;
		}
		// 建图
		row = -1; 
		bool flag;
		for(int i = 0; i < h; ++i){
			flag = true;
			for(int j = 0; j < w; ++j){
				if(1 == book[i][j]){
					if(flag) ++row;
					Gt[i][j].fi = row;
					flag = false; 
				}
				else if(2 == book[i][j]) flag = true;
			}
		}
		col = -1;
		for(int j = 0; j < w; ++j){
			flag = true;
			for(int i = 0; i < h; ++i){
				if(1 == book[i][j]){
					if(flag) ++col;
					Gt[i][j].se = col;
					flag = false; 
				}
				else if(2 == book[i][j]) flag = true;
			}
		}
		
		for(int i = 0; i < h; ++i)
			for(int j = 0; j < w; ++j) if(1 == book[i][j]) G[Gt[i][j].fi][Gt[i][j].se] = 1;
		
		//printf("row = %d, col = %d\n",row,col);
		int ans = Maxmatch();
		printf("%d\n",ans);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/CY05627/article/details/92418778