[POJ3057] Evacuation

题目

原题地址

解说

这个看着像\(BFS\)一样的东西居然还是个二分图……(当然也要用到\(BFS\)
\(BFS\)处理处每个人距离每一扇门的最短距离,并分别保存在单独一扇门对应的集合中;
若一个人能到达一扇门,则将该人与之后各时刻该门的建边;
求二分图的最大匹配,看是否能将所有人匹配完;从小时刻向大时刻枚举门,则为最优解。

代码

#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN  = 12+3;
char map[MAXN][MAXN];
int dist[MAXN][MAXN][MAXN][MAXN];
const int INF = 0x3f3f3f3f;
const int dx[4] = {-1,0,1,0};
const int dy[4] = {0,1,0,-1};
int Y,X;
vector<int> G[MAXN*MAXN*MAXN*MAXN+MAXN*MAXN];
bool used[MAXN*MAXN*MAXN*MAXN+MAXN*MAXN];
int match[MAXN*MAXN*MAXN*MAXN+MAXN*MAXN]; 
vector<int> qX,qY;
vector<int> dX,dY;
void add(int from,int to){
	G[from].push_back(to);
	G[to].push_back(from);
}
void bfs(int x, int y,int d[MAXN][MAXN]){
	d[y][x] = 0;
	queue<int> Qx;
	queue<int> Qy;	
	Qx.push(x);
	Qy.push(y);	
	while(!Qx.empty()){
		int x1 = Qx.front(); Qx.pop();
		int y1 = Qy.front(); Qy.pop();
		for(int i=0;i<4;i++){
			int x2 = x1+dx[i];
			int y2 = y1+dy[i];			
			if(0<=x2 && x2<X && 0<=y2 && y2<Y && 
			d[y2][x2]<0 && map[y2][x2] == '.'){
				d[y2][x2] = d[y1][x1] + 1;
				Qx.push(x2);
				Qy.push(y2);
			}
		}
	}
}
bool dfs(int from){
	used[from] = true;	
	for(int i=0;i<G[from].size();i++){
		int u = G[from][i];
		int w = match[u];
		if(w<0 || !used[w] && dfs(w)){
			match[u] = from;
			match[from] = u;
			return true;
		}
	}
	return false;
}
int solve(int V,int pNum){
	int res = 0;	
	if(pNum == 0){
		printf("0\n");
		return 0;
	}
	memset(match,-1,sizeof(match));
	for(int i=0;i<V;i++){
		if(match[i]<0){
			memset(used,0,sizeof(used));
			if(dfs(i)){
				res++;
			}
			if(pNum == res) {
				printf("%d\n",i/dX.size() +1);return 0 ;
			} 
		}
	}
	printf("impossible\n");
	return  0;
}
bool C(int t){
	int pNum = qX.size();
	int dNum = dX.size();	
	int V = t*dNum + pNum;
	for(int i=0;i<V;i++) G[i].clear();
	for(int i=0;i<dNum;i++)
		for(int j=0;j<pNum;j++){
			if(dist[dY[i]][dX[i]][qY[j]][qX[j]]>=0){
				for(int k=dist[dY[i]][dX[i]][qY[j]][qX[j]];k<=t;k++){
					add((k-1)*dNum+i,t*dNum+j);
				}
			}
		}			
	solve(V,pNum); 
	return 0;
}
int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		scanf("%d%d",&Y,&X);
		for(int i=0;i<Y;i++){
			getchar();
			for(int j=0;j<X;j++){
				scanf("%c",&map[i][j]);
			}
		}
		memset(dist,-1,sizeof(dist));
		dX.clear();dY.clear();
		qX.clear();qY.clear();
		for(int i=0;i<Y;i++){
			for(int j=0;j<X;j++){
				if(map[i][j]=='D'){
					bfs(j,i,dist[i][j]);
					dX.push_back(j);
					dY.push_back(i);
					
				}else if(map[i][j]=='.'){
					qX.push_back(j);
					qY.push_back(i);
				}
			}
		}
		int n = X*Y;
		int num = C(n);
	}
	return 0;
}

幸甚至哉,歌以咏志。

posted @ 2020-05-16 11:04  DarthVictor  阅读(141)  评论(0编辑  收藏  举报
莫挨老子!