zoukankan      html  css  js  c++  java
  • UVA 10801 Lift Hopping (最短路)

    最短路问题,不过起点不只是1个,终点也不止1个,因此把不同电梯的楼层分别编号,相邻楼层之间连边,不同电梯的相同楼层之间连边。

    dij的时候一次性把所有起点压到队列中,如果直接套版可以加一超级源点s和所有起点连一条dist为0的边。

    需要维护的信息:

    为了判断之前电梯有没有出现相同楼层,需要维护一个楼层到点编号的映射,为了判断终点,需要维护点编号到楼层的映射。

    #include<bits/stdc++.h>
    using namespace std;
    
    int n,k;
    
    const int maxn = 100;
    typedef long long ll;
    
    vector<int> lift[5];
    int id[5][maxn]; //判断出现 和 换乘
    int flrId[5*maxn]; //结点对应的楼层,判断终点用
    int sp[5];//speed
    
    #define PB push_back
    
    struct Edge
    {
        int v,w;
    };
    int vcnt; //结点编号从1开始
    
    vector<Edge> edges;
    vector<int> G[maxn*5+1];
    
    void addEdge(int u,int v,int w)
    {
        G[u].PB(edges.size());
        edges.PB({v,w});
    }
    
    void AddEdge(int u,int v,int w)
    {
        addEdge(u,v,w);
        addEdge(v,u,w);
    }
    
    const ll INF = 0x3f3f3f3f3f3f3f3fLL;
    ll d[maxn];
    typedef pair<int,int> Node;
    #define fi first
    #define se second
    
    ll dijkstra(int tflr = k)
    {
        fill(d+1,d+1+vcnt,INF);
        priority_queue<Node,vector<Node>,greater<Node> > q;
        for(int i = 0; i < n; i++) if(id[i][0]){
            q.push(Node(0,id[i][0])); d[id[i][0]] = 0;
        }
        while(q.size()){
            Node x = q.top(); q.pop();
            int u = x.se;
            if(flrId[u] == tflr) return d[u];
            if(d[u] != x.fi) continue;
            for(int i = 0; i < G[u].size(); i++){
                Edge &e = edges[G[u][i]];
                if(d[e.v] > d[u] + e.w){
                    d[e.v] = d[u] + e.w;
                    q.push(Node(d[e.v],e.v));
                }
            }
        }
        return INF;
    }
    
    
    
    bool sscan_l(int &x,char *&s)//非负数
    {
        while(!isdigit(*s)){
            if(!*s) return false;
            s++;
        }
        x = *s-'0';
        while(s++,isdigit(*s)) x = x*10+*s-'0';
        return true;
    }
    
    char str[233];
    void read()
    {
        for(int i = 0; i < n; i++) scanf("%d",sp+i);
        scanf("
    ");
        for(int i = 0; i < n; i++) {
            gets(str); char *p = str;
            int floor; lift[i].clear();
            while(sscan_l(floor,p)){
                lift[i].PB(floor);
            }
        }
    }
    
    void buildGraph()
    {
        for(int i = 0; i < n; i++){
            int sz = lift[i].size();
            if(sz){
                int flr = lift[i][0];
                id[i][flr] = ++vcnt;
                flrId[vcnt] = flr;
                G[vcnt].clear();
                for(int k = 0; k < i; k++) if(id[k][flr]){
                    AddEdge(vcnt,id[k][flr],60);
                }
    
                for(int j = 1; j < sz; j++){
                    flr = lift[i][j];
                    id[i][flr] = ++vcnt;
                    flrId[vcnt] = flr;
                    G[vcnt].clear();
                    for(int k = 0; k < i; k++) if(id[k][flr]){
                        AddEdge(vcnt,id[k][flr],60);
                    }
    
                    int cost = (flr-lift[i][j-1])*sp[i];
                    AddEdge(vcnt-1,vcnt,cost);
                }
            }
        }
    }
    
    void init()
    {
        memset(id,0,sizeof(id));
        vcnt = 0;
        edges.clear();
    }
    
    int main()
    {
        //freopen("in.txt","r",stdin);
        while(~scanf("%d%d",&n,&k)){
            init();
            read();
            buildGraph();
            ll ans = dijkstra();
            if(ans<INF){
                printf("%lld
    ",ans);
            }else puts("IMPOSSIBLE");
        }
        return 0;
    }
  • 相关阅读:
    Mysql::Error: Commands out of sync; you can't run this command now: SHOW TABLES解决方案
    mysql安装失败Error Nr. 1045
    TermServDevices 报错【远程服务使用者必读】
    数据库出现“提取逻辑页失败”
    Ruby学习——数据库操作
    VS2008 安装失败
    Ubuntu Server 安装图解
    C#的Enum——枚举
    SQLServer2005数据库被置为“可疑”
    ROR之include、extend、send对module、class进行扩展
  • 原文地址:https://www.cnblogs.com/jerryRey/p/4769522.html
Copyright © 2011-2022 走看看