zoukankan      html  css  js  c++  java
  • cqyz oj | 帮助Jimmy | DAG图

    Description

      "Help Jimmy" 是在下图所示的场景上完成的游戏。
      
      场景中包括多个长度和高度各不相同的平台。地面是最低的平台,高度为零,长度无限。

      Jimmy老鼠在时刻0从高于所有平台的某处开始下落,它的下落速度始终为1米/秒。当Jimmy落到某个平台上时,游戏者选择让它向左还是向右跑,它跑动的速度也是1米/秒。当Jimmy跑到平台的边缘时,开始继续下落。Jimmy每次下落的高度不能超过MAX米,不然就会摔死,游戏也会结束。

      设计一个程序,计算Jimmy到底地面时可能的最早时间。

    Input

      第一行是四个整数N,X,Y,MAX,用空格分隔。

      N是平台的数目(不包括地面),X和Y是Jimmy开始下落的位置的横竖坐标,MAX是一次下落的最大高度。

      接下来的N行每行描述一个平台,包括三个整数,X1[i],X2[i]和H[i]。H[i]表示平台的高度,X1[i]和X2[i]表示平台左右端点的横坐标。

      Jimmy的大小和平台的厚度均忽略不计。如果Jimmy恰好落在某个平台的边缘,被视为落在平台上。

      所有的平台均不重叠或相连。测试数据保证问题一定有解。

    Output

      输出一个整数,Jimmy到底地面时可能的最早时间。

    Sample Input 1 

    3 8 17 20
    0 10 8
    0 10 13
    4 14 3

    Sample Output 1

    23

    Hint

    1 <= N <= 1000,
    -20000 <= X, X1[i], X2[i] <= 20000,
    0 < H[i] < Y <= 20000(i = 1..N)。
    所有坐标的单位都是米。

     
    DAG图,只能从高往低保证了有向无环。
    把平台的左端点和右端点分别看成图上的两个点,建图。
    如果从当前这个边缘能到下面某个平台的边缘,连从当前的点到目标平台的左右边缘的点各一条边,
    边权为 平台高度差+从这个点落到目标平台上后跑到边缘的距离。
    出发点是当做左右边缘为都为X,高度为Y的平台
    跑一个最短路即可
    #include<cstdio>
    #include<iostream>
    #include<queue>
    #include<algorithm>
    #define lch(x) (x<<1)
    #define rch(x) (x<<1|1)
    using namespace std;
    const int maxn = 1005, maxm = maxn*2, inf = 0x3f3f3f3f;
    
    struct plf {
        int l, r;
        int h;
        friend bool operator < (const plf& a, const plf& b) {
            return a.h < b.h || (a.h == b.h && a.l < b.l);
        }
    }a[maxn];
    
    int fir[maxn*2], ne[maxm*2], to[maxm*2], w[maxm*2], np;
    void add(int x, int y, int z) {
        ne[++np] = fir[x];
        fir[x] = np;
        to[np] = y;
        w[np] = z;
    }
    
    int n, MAX;
    int X, Y;
    void input() {
        cin >> n >> X >> Y >> MAX;
        for(int i=1, l, r, h; i<=n; i++) {
            scanf("%d%d%d", &l, &r, &h);
            a[i] = (plf){l, r, h};
        }
        a[++n] = (plf){X, X, Y};
    }
    
    int dis[maxn*2], inq[maxn*2];
    void BFS(int s) {
        queue<int> Q;
        for(int i=0; i<=n*2; i++) dis[i] = inf, inq[i] = 0;
        dis[s] = 0; inq[s] = 1;
        Q.push(s);
        
        while(!Q.empty()) {
            int u = Q.front(); Q.pop();
            inq[u] = 0;
            for(int i=fir[u]; i; i=ne[i]) {
                int v = to[i];
                if(dis[v] > dis[u] + w[i]) {
                    dis[v] = dis[u] + w[i];
                    if(!inq[v]) Q.push(v), inq[v] = 1;
                }
            }
        }
    }
    
    inline bool inRange(int x, int l, int r) { return l<=x && x<=r; }
    
    void solve() {
        // 建图 
        sort(a+1, a+n+1);
        int ok1[maxn], ok2[maxn];
        
        for(int i=1; i<=n; i++) {
            ok1[i]=0, ok2[i]=0;
            for(int j=i-1; (!ok1[i] || !ok2[i]) && j>=1 && a[i].h - a[j].h <= MAX; j--) {
                if(!ok1[i] && inRange(a[i].l, a[j].l, a[j].r)) {
                    add(lch(i), lch(j), (a[i].l - a[j].l) + (a[i].h - a[j].h));
                    add(lch(i), rch(j), (a[j].r - a[i].l) + (a[i].h - a[j].h));
                    ok1[i] = 1;
                }
                if(!ok2[i] && inRange(a[i].r, a[j].l, a[j].r)) {
                    add(rch(i), lch(j), (a[i].r - a[j].l) + (a[i].h - a[j].h));
                    add(rch(i), rch(j), (a[j].r - a[i].r) + (a[i].h - a[j].h));
                    ok2[i] = 1;
                }
            }
        }
        
        // 特殊处理地面 
        for(int i=1; i<=n && a[i].h <= MAX; i++) {
            if(!ok1[i]) add(lch(i), 0, a[i].h);
            if(!ok2[i]) add(rch(i), 0, a[i].h);
        }
        
        int rt;
        for(rt=1; rt<=n; rt++)
            if(a[rt].l == X && a[rt].h == Y) break;
        
        BFS(lch(rt));
        printf("%d", dis[0]);
    }
    
    int main() {
        input();
        solve();
        return 0;
    }
    View Code
  • 相关阅读:
    ndarray转PIL
    215. 数组中的第K个最大元素
    pytorch的分布式
    剑指 Offer 06. 从尾到头打印链表
    最长公共子序列
    剑指 Offer 57
    剑指 Offer 59
    剑指 Offer 48. 最长不含重复字符的子字符串
    Python线程池
    Python 常用内置函数
  • 原文地址:https://www.cnblogs.com/de-compass/p/11822198.html
Copyright © 2011-2022 走看看