• man


    Description
    n间房子高度不同,Man 要从最矮的房子按照高度顺序跳到最高的房子,你知道房子的顺序,以及Man一次最远可以跳多远,相邻的房子至少有1的距离,房子的宽不计,现在由你安排相邻房子的距离,使Man可以跳到最高的房子且让最矮的房子与最高的房子距离最远,没有合法方案输出-1
    Input
    第一行一个整数T表示数据组数,每组数据第一行两个整数n,d分别表示房子数量以及Man一次可以跳多远,第二行n个整数用空格隔开,第i个整数表示第i个房子的高度
    Output
    每组数据输出‘Case ’+第几组数据+‘: ’+最远距离
    Sample Input
    样例输入:
    3
    4 4
    20 30 10 40
    5 6
    20 34 54 10 15
    4 2
    10 20 16 13

    样例输出:
    Case 1: 3
    Case 2: 3
    Case 3: -1
    HINT
    数据范围:
    对于40%的数据 n < 8 t=2 d < 10
    对于100%的数据 n < 10001 d < 1000000 t < 100 高度 < 1000000


    差分约束典型题…
    关于如何理解 选取起点和终点中靠左边的点, 开始跑一遍最短路就可以得到答案, 这里提供一种思路: 在跑最短路之前, dis被设置为INF, 跑最短路的过程就是为了使dis满足约束条件. 只要跑完最短路, dis[t]必定就是最大的. 至于为什么要选取起点和终点中靠左的开始跑最短路, 理由是dis[t]维护的是s到t的距离的最大值. 这个假如t在s的左边, 则距离为负, 则维护的实际上是t到s的距离的最小值. 因此要确保起始遍历的点在终结点的左边.

    #include<stdio.h>
    #include<iostream>
    #include<string.h>
    #include<algorithm>
    #include<math.h>
    using namespace std;
    const int maxN = 1000;
    const int maxRoom = (int)1e6;
    struct building
    {
        int h, id;
    }a[maxN];
    int head[maxN];
    int top;
    struct edge
    {
        int v, w, next;
    }G[maxN << 2];
    void addEdge(int u, int v, int w)
    {
        G[top].v = v;
        G[top].w = w;
        G[top].next = head[u];
        head[u] = top ++;
    }
    int operator <(building x, building y)
    {
        return x.h < y.h;
    }
    int dis[maxN];
    int Q[maxRoom];
    int inQ[maxN];
    int vis[maxN];
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("man.in", "r", stdin);
        freopen("man.out", "w", stdout);
        #endif
        ios::sync_with_stdio(false);
        int T, _case = 0;
        for(cin >> T; T; T --)
        {
            int n, d;
            cin >> n >> d;
            memset(head, - 1, sizeof(head));
            top = 0;
            for(int i = 0; i < n; i ++)
            {
                cin >> a[a[i].id = i].h;
                if(i)
                    addEdge(i, i - 1, - 1);
            }
            sort(a, a + n);
            for(int i = 1; i < n; i ++)
            {
                int u = a[i - 1].id, v = a[i].id;
                if(u > v)
                    swap(u, v);
                addEdge(u, v, d);
            }
            int L = 0, R = 1, s = a[0].id, t = a[n - 1].id;
            if(s > t)
                swap(s, t);
            Q[L] = s;
            memset(dis, 127, sizeof(dis));
            dis[s] = 0;
            memset(inQ, 0, sizeof(inQ));
            inQ[s] = 1;
            memset(vis, 0, sizeof(vis));
            vis[s] = 1;
            int flag = 0;
            while(L < R)
            {
                int u = Q[L];
                for(int i = head[u]; i != - 1; i = G[i].next)
                {
                    int v = G[i].v;
                    if(dis[u] + G[i].w >= dis[v])
                        continue;
                    dis[v] = dis[u] + G[i].w;
                    if(! inQ[v])
                    {
                        inQ[v] = 1;
                        Q[R ++] = v;
                        vis[v] ++;
                        if(vis[v] > n)
                        {
                            flag = 1;
                            break;
                        }
                    }
                }
                inQ[u] = 0;
                L ++;
            }
            if(flag)
                printf("Case %d: -1
    ", ++ _case);
            else
                printf("Case %d: %d
    ", ++ _case, abs(dis[t]));
        }
    }
  • 相关阅读:
    前端与算法 leetcode 387. 字符串中的第一个唯一字符
    前端与算法 leetcode 283. 移动零
    前端与算法 leetcode 125. 验证回文串
    前端与算法 leetcode 7. 整数反转
    vue-create 报错 command failed: yarn --registry=https://registry.npm.taobao.org --disturl=https://npm.taobao.org/dist 完美解决方案
    前端与算法 leetcode 242. 有效的字母异位词
    javascript 解决默认取整的坑(目前已知的最佳解决方案)
    Excel中countif函数的使用方法
    excel的函数基础——if条件函数该怎么用?
    excel 这也许是史上最好最全的VLOOKUP函数教程
  • 原文地址:https://www.cnblogs.com/ZeonfaiHo/p/6402843.html
Copyright © 2020-2023  润新知