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复制那点事
    全排列问题
    56. Merge Interval
    2. Add Two Numbers
    20. Valid Parentheses
    121. Best Time to Buy and Sell Stock
    120. Triangle
    96. Unique Binary Search Trees
    91. Decode Ways
    72. Edit Distance
  • 原文地址:https://www.cnblogs.com/jerryRey/p/4769522.html
Copyright © 2011-2022 走看看