• [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
    ");
    		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
    ",i/dX.size() +1);return 0 ;
    			} 
    		}
    	}
    	printf("impossible
    ");
    	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;
    }
    

    幸甚至哉,歌以咏志。

  • 相关阅读:
    第一阶段冲刺第三天
    C语言printf函数求值顺序
    计算文件的MD5值
    SWFUpload后台取数据
    swfupload的使用方式
    文件上传的几种方式
    自定义缓存
    发邮件
    生成验证码
    将序列化成json格式后日期(毫秒数)转成日期格式
  • 原文地址:https://www.cnblogs.com/DarthVictor/p/12899487.html
Copyright © 2020-2023  润新知