LightOJ 1150 Ghosts! 二分圖 BFS 枚舉

題意:給一個矩陣,"."代表空地,“#”代表迷霧,“G”代表鬼,“H”代表人,每個鬼要嚇唬一個人,然後回到自己的位置,每走一格消耗一分鐘,嚇唬人消耗兩分鐘,每個鬼只能嚇唬一個人,求需要消耗的最小時間。

思路:用BFS求出所有鬼和人之間的邊,按照長短排序,每次放入一條邊然後求最大匹配,如果最大匹配與人的數量相同則成功,輸出當前邊的長度。

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <string>
#define N 300
#define M 600
#define ll long long
#define INF 0x7fffffffffffffff
using namespace std;
struct Edge{
	int h;
	int g;
	int length;
	Edge(int _h,int _g,int _l){
		this->h = _h,this->g = _g,this->length = _l;
	}
};
struct Node{
	int x;
	int y;
	int step;
	Node(int _x,int _y,int _s){
		x=_x,y=_y,step = _s;
	}
};


vector<Edge>edges;//存邊
int maph[N][N];//人編號
char map[N][N];//地圖
bool mem[N][N];

vector <int>connect[M];

int match[M];
bool used[M];
bool canfound(int x){
	for(int i=0;i<connect[x].size();i++){
		int tmp = connect[x][i];
		if(!used[tmp]){
			used[tmp] = 1;
			if(match[tmp] == -1 || canfound(match[tmp])){
				match[tmp] = x;
				return true;
			}
		}
	}
	return false;
}

int t,n;

int mx[4] = {-1,1,0,0};
int my[4] = {0,0,-1,1};

void bfs(int x,int y,int id){
	queue<Node>Q;
	Q.push(Node(x,y,0));
	while (!Q.empty())
	{
		Node tmp = Q.front();Q.pop();
		if(mem[tmp.x][tmp.y]){
			continue;
		}else{
			mem[tmp.x][tmp.y] = 1;
		}
		if(map[tmp.x][tmp.y] == '#'){
			continue;
		}
		if(maph[tmp.x][tmp.y] != 0){
			edges.push_back(Edge(maph[tmp.x][tmp.y],id,tmp.step*2+2));
		}
		for(int i=0;i<4;i++){
			if(tmp.x+mx[i] >= 1 && tmp.x+mx[i] <= n && tmp.y+my[i] >= 1 && tmp.y+my[i] <= n){
				Q.push(Node(tmp.x+mx[i],tmp.y+my[i],tmp.step+1));
			}

		}
	}
}

bool cmp(Edge a,Edge b){
	return a.length < b.length;
}

int main(){
	int i,j,k;
	scanf("%d",&t);
	for(i=1;i<=t;i++){
		int hcnt = 0,gcnt = 0;
		memset(maph,0,sizeof(maph));
		memset(map,0,sizeof(map));
		edges.clear();
		for(j=0;j<M;j++){
			connect[j].clear();
		}
		scanf("%d",&n);
		getchar();
		//輸入
		for(j=1;j<=n;j++){
			for(k=1;k<=n;k++){
				scanf("%c",&map[j][k]);
				if(map[j][k] == 'G'){
					gcnt++;
				}
				if(map[j][k] == 'H'){
					hcnt++;
					maph[j][k] = hcnt;
				}
			}
			getchar();
		}
		int cnt = 0;
		for(j=1;j<=n;j++){
			for(k=1;k<=n;k++){
				if(map[j][k] == 'G'){
					cnt++;
					memset(mem,0,sizeof(mem));//清空記錄
					bfs(j,k,cnt);
				}
			}
		}
		sort(edges.begin(),edges.end(),cmp);
		int ans = -1;
		for(j=0;j<edges.size();j++){
			connect[edges[j].h].push_back(edges[j].g);
			memset(match,-1,sizeof(match));
			int res = 0;
			for(k=1;k<=hcnt;k++){
				memset(used,0,sizeof(used));
				if(canfound(k)){
					res++;
				}
			}
			if(res == hcnt){
				ans = edges[j].length;
				break;
			}
		}
		if(ans != -1){
			printf("Case %d: %d\n",i,ans);
		}else{
			printf("Case %d: Vuter Dol Kupokat\n",i);
		}

	}
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章