hdu 3440(差分约束好题)

House Man

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


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
题意:一个人要从高度最低的房子开始跳到高度最高的房子,每次只能跳到与它本身的高度相邻的房子,每次能够跳的最大距离是D,问最低的房子和最高的房子的最大距离.
题解:这题我首先就想排序,然后再按编号对两个房子连一条边..结果死活做不出来,然后发现漏掉了一点,我们是要考虑房子的编号的。。有向边我们规定是从编号小的连向编号大的,所以我们无论是建图还是找最短路,都要从编号小的找到编号大的。这一点比较难想到.然后就很简单了,如果有负环或者没有松弛就不可达。其余情况输出最小值。
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <iostream>
#include <stdlib.h>
#include <queue>
using namespace std;
const int N = 1005;
const int INF = 1<<30;
struct Node{
    int h,id;
}node[N];
struct Edge{
    int v,w,next;
}edge[N*(N-1)];
int head[N],n;
void addEdge(int u,int v,int w,int &k){
    edge[k].v = v,edge[k].w=w,edge[k].next=head[u],head[u]=k++;
}
int cmp(Node a,Node b){
    return a.h<b.h;
}
bool vis[N];
int low[N];
int time[N];
int spfa(int s,int e){
    queue<int>q;
    for(int i=1;i<=n;i++){
        vis[i] = false;
        time[i] = 0;
        low[i] = INF;
    }
    time[s]++;
    low[s] = 0;
    q.push(s);
    while(!q.empty()){
        int u = q.front();
        q.pop();
        vis[u] = false;
        for(int k = head[u];k!=-1;k=edge[k].next){
            int v = edge[k].v,w=edge[k].w;
            if(low[v]>low[u]+w){
                low[v] = low[u]+w;
                if(!vis[v]){
                    vis[v] = true;
                    q.push(v);
                    if(time[v]++>n) return -1;
                }
            }
        }
    }
    if(low[e]>=INF) return -1;
    return low[e];
}
int main()
{
    int tcase;
    scanf("%d",&tcase);
    int t=1;
    while(tcase--){

        memset(head,-1,sizeof(head));
        int D;
        int tot = 0;
        scanf("%d%d",&n,&D);
        for(int i=1;i<=n;i++){
            scanf("%d",&node[i].h);
            node[i].id = i;
        }
        sort(node+1,node+1+n,cmp);
        for(int i=1;i<n;i++){
            addEdge(i+1,i,-1,tot);
        }
        for(int i=1;i<n;i++){
            int a = max(node[i].id,node[i+1].id);
            int b = min(node[i].id,node[i+1].id);
            addEdge(b,a,D,tot);
        }
        int s = min(node[n].id,node[1].id);
        int e = max(node[n].id,node[1].id);
        int c = spfa (s,e);
        printf ("Case %d: %d
",t++,c);
    }
}
原文地址:https://www.cnblogs.com/liyinggang/p/5504288.html