题解 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;
}

原文地址:https://www.cnblogs.com/White-star/p/11442963.html

时间: 2024-08-01 18:02:56

题解 poj3057 Evacuation的相关文章

解题报告 之 POJ3057 Evacuation

解题报告 之 POJ3057 Evacuation Description Fires can be disastrous, especially when a fire breaks out in a room that is completely filled with people. Rooms usually have a couple of exits and emergency exits, but with everyone rushing out at the same time

POJ3057 Evacuation 解题报告

这道题的难点应该就是想到这是一道二分图匹配 想到这点以后,就是建图了 //by baobaopangzi88 #include <iostream> #include <sstream> #include <ios> #include <iomanip> #include <functional> #include <algorithm> #include <vector> #include <string>

[POJ3057]Evacuation(二分图匹配,BFS,二分,好题)

题目链接:http://poj.org/problem?id=3057 题意:<挑战>P230的题. 首先预处理出所有人到所有门的最短距离dis(pxi,pyi,dxj,dyj),然后二分答案. 拿二分出的时间t判断,判断的时候把每一个门拆成t个点,与人连起来,求最大匹配,看匹配结果是否满足与总人数相等. 因为要保证每一个人都在某一个门的一秒出去,所以可以用上述建图方法保证. RE了不知道在哪里.. 1 #include <algorithm> 2 #include <ios

Emergency Evacuation题解

题目 The Japanese government plans to increase the number of inbound tourists to forty million in the year 2020, and sixty million in 2030. Not only increasing touristic appeal but also developing tourism infrastructure further is indispensable to acco

Codeforces Gym 100002 E &quot;Evacuation Plan&quot; 费用流

"Evacuation Plan" Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100002 Description The City has a number of municipal buildings and a number of fallout shelters that were build specially to hide municipal workers in case 

解题报告 之 POJ2175 Evacuation Plan

解题报告 之 POJ2175 Evacuation Plan Description The City has a number of municipal buildings and a number of fallout shelters that were build specially to hide municipal workers in case of a nuclear war. Each fallout shelter has a limited capacity in term

洛谷 P1079 Vigen&#232;re 密码 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:https://www.luogu.org/problem/show?pid=1079 题目描述 16 世纪法国外交家 Blaise de Vigenère 设计了一种多表密码加密算法――Vigenère 密 码.Vigenère 密码的加密解密算法简单易用,且破译难度比较高,曾在美国南北战争中为 南军所广泛使用. 在密码学中,我们称需要加密的信息为明文,用 M 表示:称加密后的信息为密文,用 C 表示:而密钥是一种

8.8联考题解

今天的T1让我怀疑我是不是在做奥赛题--这考的是什么知识点啊这个,会不会用绝对值函数? Evensgn 的债务 时间限制: 1 Sec  内存限制: 128 MB 题目描述 Evensgn 有一群好朋友,他们经常互相借钱.假如说有三个好朋友A,B,C.A 欠 B 20 元,B 欠 C 20 元,总债务规模为 20+20=40 元.Evensgn 是个追求简约的人,他觉得这样的债务太繁杂了.他认为,上面的债务可以完全等价为 A 欠C20 元,B 既不欠别人,别人也不欠他.这样总债务规模就压缩到了 

POJ 2533 - Longest Ordered Subsequence(最长上升子序列) 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:http://poj.org/problem?id=2533 Description A numeric sequence of ai is ordered if a1 < a2 < ... < aN. Let the subsequence of the given numeric sequence (a1, a2, ..., aN) be any sequence (ai1, ai2, ..., aiK)