大江东去,浪淘尽,千古风流人物。故垒西边,人道是,三国周郎赤壁。乱石穿空,惊涛拍岸,卷起千堆雪。江山如画,一时多少豪杰。遥想公瑾当年,小乔初嫁了,雄姿英发。羽扇纶巾,谈笑间,樯橹灰飞烟灭。故国神游,多情应笑我,早生华发。人生如梦,一尊还酹江月。

题解 poj3057 Evacuation

算法:匈牙利算法

复杂度:不好算,懒得算

这道题我调了两个半小时,代码长,细节多,现总结一下栽过的坑

  1. 此题数组传参的方式很好,能够降低代码难度,值得学习
  2. 如何使人和时间、门的二元组互不冲突很重要
  3. 如果点无冲突用链表,否则用vector
  4. 点是从0开始建的,初始化match数组不能用0,我虽然注意到了这一点却没调出来

丑陋的代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;

#define rep(i,a,b) for(int i=a;i<b;++i)
#define go(i,a,b) for(int i=a;i<=b;++i)
#define mem(a,b) memset(a,b,sizeof(a))

const int N=1000010;

int n,m,d[15][15][15][15],match[N],cnt=0,tot=0,head[N],p,door,ans=0;
int match2[N];
bool vis[N];
char g[15][15];
int nd[4][2]= {{1,0},{-1,0},{0,1},{0,-1}},V;
vector<int> dx,dy,px,py,e[250];
/*struct edge{
	int nxt,v;
}e[N];

void add(int u,int v){
	e[cnt]=(edge){head[u],v};
	head[u]=cnt++;
}*/

void add(int u,int v){
	e[u].push_back(v);
}

void bfs(int x,int y,int d[15][15]){
	queue<int>qx,qy;
	d[x][y]=0;
	qx.push(x),qy.push(y);
	while(!qx.empty()){
		x=qx.front();qx.pop();
		y=qy.front();qy.pop();
		go(k,0,3){
			int x2=x+nd[k][0],y2=y+nd[k][1];
			if(g[x2][y2]=='.'&&d[x2][y2]<0){
				d[x2][y2]=d[x][y]+1;
				qx.push(x2),qy.push(y2);
			}
		}
	}
}

bool dfs(int u){
	/*for(int i=head[u];i+1;i=e[i].nxt){
		int v=e[i].v;
		if(vis[v]) continue;
		vis[v]=1;
		if(!match[v]||dfs(match[v])){
			match[v]=u;match[u]=v;
			return 1;
		}
	}*/
	for(int i=0;i<e[u].size();++i){
		int v=e[u][i];
		if(vis[v]) continue;
		vis[v]=1;
		if(match[v]==-1||dfs(match[v])){
			match[v]=u;match2[u]=v;
			return 1;
		}
	}
	return 0;
}

void work(int k){
	for(int i=0;i<p;++i){
		if(match2[i]==-1){
			for(int j=0;j<door*k;j++) vis[j]=false;
			ans+=dfs(i);
		}
	}
}

void solve(){
	tot=n*m;
	dx.clear(),dy.clear(),px.clear(),py.clear();
	go(i,0,p-1)
		e[i].clear();
	mem(d,-1);
	rep(x,0,n)
		rep(y,0,m){
			if(g[x][y]=='D'){
				dx.push_back(x),dy.push_back(y);
				bfs(x,y,d[x][y]);
			}
			else if(g[x][y]=='.'){
				px.push_back(x),py.push_back(y);
			}
		}
	door=dx.size(),p=px.size();
	if(!p){
		puts("0");
		return;
	}
	mem(match,-1);mem(match2,-1); 
	mem(head,-1);cnt=0;
	ans=0;
	int k;
	for(k=1;k<tot;++k){
		
		//for(int i=0;i<=30;++i) printf("%d %d ",match[i],match2[i]);
		//puts("");
		
		rep(i,0,p)
			rep(j,0,door){
				
				//printf("%d\n",d[dx[j]][dy[j]][px[i]][py[i]]);
				
				if(d[dx[j]][dy[j]][px[i]][py[i]]!=-1&&d[dx[j]][dy[j]][px[i]][py[i]]<=k)
					add(i,j+door*(k-1));
			}
			
		work(k);
		
	//	printf("%d\n",ans);
		
		if(ans==p){
			printf("%d\n",k);
			return;
		}
	}
	if(k==tot) puts("impossible");
	return;
}

int main(){
	//freopen("input.txt","r",stdin);
	//freopen("wrong.txt","w",stdout);
	int T;
	scanf("%d",&T);
	while(T--){
		cin>>n>>m;
		go(i,0,n-1) scanf("%s",g[i]);
		//printf("%d\n",T);
		solve();
	}
	//int x=5;
	//printf("%d",x*x);
	return 0;
}
posted @ 2019-09-01 17:40  White_star  阅读(154)  评论(0编辑  收藏  举报
}