• HDU 3440 House Man(编号排序+线性差分约束跑最短路)


    House Man

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 3605    Accepted Submission(s): 1517


    Problem Description
    In Fuzhou, there is a crazy super man. He can’t fly, but he could jump from housetop to housetop. Today he plans to use N houses to hone his house hopping skills. He will start at the shortest house and make N-1 jumps, with each jump taking him to a taller house than the one he is jumping from. When finished, he will have been on every house exactly once, traversing them in increasing order of height, and ending up on the tallest house.
    The man can travel for at most a certain horizontal distance D in a single jump. To make this as much fun as possible, the crazy man want to maximize the distance between the positions of the shortest house and the tallest house.
    The crazy super man have an ability—move houses. So he is going to move the houses subject to the following constraints:
    1. All houses are to be moved along a one-dimensional path.
    2. Houses must be moved at integer locations along the path, with no two houses at the same location.
    3. Houses must be arranged so their moved ordering from left to right is the same as their ordering in the input. They must NOT be sorted by height, or reordered in any way. They must be kept in their stated order.
    4. The super man can only jump so far, so every house must be moved close enough to the next taller house. Specifically, they must be no further than D apart on the ground (the difference in their heights doesn't matter).
    Given N houses, in a specified order, each with a distinct integer height, help the super man figure out the maximum possible distance they can put between the shortest house and the tallest house, and be able to use the houses for training.
     
    Input
    In the first line there is an integer T, indicates the number of test cases.(T<=500)
    Each test case begins with a line containing two integers N (1 ≤ N ≤ 1000) and D (1 ≤ D ≤1000000). The next line contains N integer, giving the heights of the N houses, in the order that they should be moved. Within a test case, all heights will be unique.
     
    Output
    For each test case , output “Case %d: “first where d is the case number counted from one, then output a single integer representing the maximum distance between the shortest and tallest house, subject to the constraints above, or -1 if it is impossible to lay out the houses. Do not print any blank lines between answers.
     
    Sample Input
    3 4 4 20 30 10 40 5 6 20 34 54 10 15 4 2 10 20 16 13
     
    Sample Output
    Case 1: 3 Case 2: 3 Case 3: -1
     
    Author
    jyd
     
    Source
     
    题目意思:
    n个房子,线性一维排列,房子有高度,房子不能在同一个位置,现在有一个超人,从最低的房子开始跳,
    每次跳的房子的高度要求比上一个房子的高度高,每个房子都要跳,最后要停在最高的房子上
    你可以随意改变任意房子之间的距离,但是不能改变房子的相对位置
    每次超人最多跳D远,问你超人跳完之后
    最低的房子和最高的房子之间的距离最大可以是多少?
    分析:
    每次要求跳的高度递增且要是最高的房子结束
    说明跳的房子的顺序已经排列好了
    给线性一维上的房子编个号,1到n
    按照高度升序排序,得到的编号顺序就是跳的顺序
    假设x[i]:表示房子i的位置
    x[i]-x[j]表示房子i和j之间的距离,i>j
    比如样例1
    高度:20 30 10 40
    编号:1  2  3  4
    按照高度升序排序之后,跳的顺序为:3 1 2 4
    对每次跳:
    x[3]-x[1]<=d
    x[2]-x[1]<=d
    x[4]-x[2]<=d
    注意每次都是编号大的房子位置减去编号小的房子位置,这样才能得到两者间的距离
    隐藏关系:同一个位置不能有两个房子
    则:x[i]-x[i-1]>=1,i属于2到n
    变形一下:x[i-1]-x[i]<=-1
    现在所有的约束关系是都是这个形式:x[i]-x[j]<=x
    开始建图,j->i 权值为x
    比如上面的样例:
    1->3 权值4
    11->2 权值4
    2->4 权值4
    2->1 权值-1
    3->2 权值-1
    题目要求是从最低的房子到最高的房子的最大距离
    注意:是最高房子和最低房子中编号小的房子出发,做起点
    最高房子和最低房子中编号大的房子结束,做终点
    因为高的房子编号不一定大,低的房子编号不一定小
    然后因为表达式是x[i]-x[j]<=x
    所以是求最短路,不能使用dj,因为存在负权
    推荐使用spfa
    code:
    #include<stdio.h>
    #include<iostream>
    #include<math.h>
    #include<string.h>
    #include<set>
    #include<map>
    #include<list>
    #include<math.h>
    #include<queue>
    #include<algorithm>
    using namespace std;
    typedef long long LL;
    #define INF 9999999999
    #define me(a,x) memset(a,x,sizeof(a))
    int mon1[13]= {0,31,28,31,30,31,30,31,31,30,31,30,31};
    int mon2[13]= {0,31,29,31,30,31,30,31,31,30,31,30,31};
    int dir[4][2]= {{0,1},{0,-1},{1,0},{-1,0}};
    
    int getval()
    {
        int ret(0);
        char c;
        while((c=getchar())==' '||c=='
    '||c=='
    ');
        ret=c-'0';
        while((c=getchar())!=' '&&c!='
    '&&c!='
    ')
            ret=ret*10+c-'0';
        return ret;
    }
    void out(int a)
    {
        if(a>9)
            out(a/10);
        putchar(a%10+'0');
    }
    
    #define max_v 1005
    struct node
    {
        int v;
        LL w;
        node(int vv=0,LL ww=0):v(vv),w(ww) {}
    };
    struct node1
    {
        int id,v;
    }p[max_v];
    bool cmp(node1 a,node1 b)
    {
        return a.v<b.v;
    }
    LL dis[max_v];
    int vis[max_v];
    int cnt[max_v];
    vector<node> G[max_v];
    queue<int> q;
    
    void init()
    {
        for(int i=0; i<max_v; i++)
        {
            G[i].clear();
            dis[i]=INF;
            vis[i]=0;
            cnt[i]=0;
        }
        while(!q.empty())
            q.pop();
    }
    
    int spfa(int s,int n)
    {
        vis[s]=1;
        dis[s]=0;
        q.push(s);
        cnt[s]++;
    
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            vis[u]=0;
    
            for(int j=0; j<G[u].size(); j++)
            {
                int v=G[u][j].v;
                LL w=G[u][j].w;
    
                if(dis[v]>dis[u]+w)
                {
                    dis[v]=dis[u]+w;
                    if(vis[v]==0)
                    {
                        q.push(v);
                        cnt[v]++;
                        vis[v]=1;
    
                        if(cnt[v]>n)
                            return 0;
                    }
                }
            }
        }
        return 1;
    }
    int f(int u,int v)
    {
        for(int j=0; j<G[u].size(); j++)
        {
            if(G[u][j].v==v)
                return 0;
        }
        return 1;
    }
    int main()
    {
        int t,ca=1;
        scanf("%d",&t);
        while(t--)
        {
            int n,d;
            scanf("%d %d",&n,&d);
            for(int i=1;i<=n;i++)
            {
                scanf("%d",&p[i].v);
                p[i].id=i;
            }
            sort(p+1,p+1+n,cmp);
            init();
            int x,y;
            for(int i=1;i<=n-1;i++)
            {
                x=p[i].id;
                y=p[i+1].id;
                int u=max(x,y);
                int v=min(x,y);
                if(f(v,u))
                    G[v].push_back(node(u,d));
            }
            for(int i=2;i<=n;i++)
            {
                if(f(i,i-1))
                    G[i].push_back(node(i-1,-1));
            }
            int s=min(p[n].id,p[1].id);//!!!高的房子不一定编号大,低的房子不一定编号小,因为x[i]-x[j]<=x,要求i>j 请注意
            int e=max(p[n].id,p[1].id);
            int flag=spfa(s,n);
            printf("Case %d: ",ca++);
            if(flag==0)
            {
                printf("-1
    ");
            }else
            {
                printf("%lld
    ",dis[e]);
            }
        }
        return 0;
    }
    
    /*
    题目意思:
    n个房子,线性一维排列,房子有高度,房子不能在同一个位置,现在有一个超人,从最低的房子开始跳,
    每次跳的房子的高度要求比上一个房子的高度高,每个房子都要跳,最后要停在最高的房子上
    你可以随意改变任意房子之间的距离,但是不能改变房子的相对位置
    每次超人最多跳D远,问你超人跳完之后
    最低的房子和最高的房子之间的距离最大可以是多少?
    
    分析:
    每次要求跳的高度递增且要是最高的房子结束
    说明跳的房子的顺序已经排列好了
    给线性一维上的房子编个号,1到n
    按照高度升序排序,得到的编号顺序就是跳的顺序
    
    假设x[i]:表示房子i的位置
    x[i]-x[j]表示房子i和j之间的距离,i>j
    比如样例1
    高度:20 30 10 40
    编号:1  2  3  4
    按照高度升序排序之后,跳的顺序为:3 1 2 4
    对每次跳:
    x[3]-x[1]<=d
    x[2]-x[1]<=d
    x[4]-x[2]<=d
    注意每次都是编号大的房子位置减去编号小的房子位置,这样才能得到两者间的距离
    
    隐藏关系:同一个位置不能有两个房子
    则:x[i]-x[i-1]>=1,i属于2到n
    变形一下:x[i-1]-x[i]<=-1
    现在所有的约束关系是都是这个形式:x[i]-x[j]<=x
    开始建图,j->i 权值为x
    比如上面的样例:
    1->3 权值4
    11->2 权值4
    2->4 权值4
    2->1 权值-1
    3->2 权值-1
    题目要求是从最低的房子到最高的房子的最大距离
    注意:是最高房子和最低房子中编号小的房子出发,做起点
    最高房子和最低房子中编号大的房子结束,做终点
    因为高的房子编号不一定大,低的房子编号不一定小
    然后因为表达式是x[i]-x[j]<=x
    所以是求最短路,不能使用dj,因为存在负权
    推荐使用spfa
    
    */
    心之所向,素履以往
  • 相关阅读:
    C# 类型的创建
    C# 中4个访问符和8个修饰符详解
    C#命名空间详解namespace
    ContextMenuStrip 添加在窗体。点击右键不能显示问题解答
    C# 学习笔记 C#基础
    React-Navigation web前端架构
    Css animation 与 float 、flex 布局问题
    javaScript 工作必知(十一) 数组常用方法实现
    Vue 父子组件传值 props
    kafka 参数配置 1
  • 原文地址:https://www.cnblogs.com/yinbiao/p/10003350.html
Copyright © 2020-2023  润新知