hdoj 3440 House Man 【差分约束】 【经典建模】

来源:互联网 发布:淘宝质量问题如何投诉 编辑:程序博客网 时间:2024/04/30 16:29


House Man

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


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
34 4 20 30 10 40 5 6 20 34 54 10 15 4 2 10 20 16 13
 

Sample Output
Case 1: 3Case 2: 3Case 3: -1
 
题意:有N个在一条直线上的房子, 每个房子有着不同的高度。一个超人可以将这些房子左右移动,但是他不能改变房子之间的相对位置。现在他要经过N-1次跳跃从最低的房子跳到最高的房子上面(这意味着他必须从最低的房子 按高度递增  依次经过N-2个房子到达最高的房子)。现在给出超人能够跳的最远水平距离D(两个房子间的水平距离小于或者等于D就说明可以从较低的房子跳到较高的房子上)。  问存不存在一种方案:能够使超人用N-1次跳跃并经过所有的房子跳到最高的房子,若存在方案,输出最低房子与最高房子所能相差的最大距离,否则输出-1。

建图,我是排序后模拟出来的。

思路:用一个结构体记录房子的高度以及位置,把每个房子虚拟成一个节点即它的位置。

建边一:相邻的房子至少距离为1(未排序前);这个好想

建边二:将房子按高度递增排序后,选择 最低房子 和 最高房子中位置较小的为起点,另一个为终点。那么对于相邻的房子,我们可以建一条 位置小的指向位置大的边且权值为D;

建完图就是求最短路了,存在负环时最短路不存在。

AC代码:

#include <cstdio>#include <cstring>#include <queue>#include <algorithm>#define MAXN 1000+10 #define MAXM 2000+10 #define INF 1000000000 using namespace std;struct Edge{int from, to, val, next;}edge[MAXM];struct house//房子高度 以及位置 {int height, pos;}num[MAXN];bool cmp(house a, house b){return a.height < b.height;}int dist[MAXN];int used[MAXN];bool vis[MAXN];int head[MAXN], top;int N, D;int sx, ex;//起点 终点 void init(){top = 0;memset(head, -1, sizeof(head));}void addEdge(int u, int v, int w){Edge E = {u, v, w, head[u]};edge[top] = E;head[u] = top++;}void getMap(){for(int i = 1; i <= N; i++){scanf("%d", &num[i].height);num[i].pos = i;}sort(num+1, num+N+1, cmp);sx = min(num[1].pos, num[N].pos);//小的当作起点 ex = max(num[1].pos, num[N].pos);//大的当作终点 for(int i = 1; i <= N-1; i++){if(num[i].pos > num[i+1].pos)//小的指向大的 addEdge(num[i+1].pos, num[i].pos, D); elseaddEdge(num[i].pos, num[i+1].pos, D);addEdge(i+1, i, -1);//相邻房子 记录至少为一 }}void SPFA(int s, int e){queue<int> Q;for(int i = 1; i <= N; i++){dist[i] = i==s ? 0 : INF;used[i] = 0;vis[i] = false; } vis[s] = true;used[s]++;Q.push(s);while(!Q.empty()){int u = Q.front();Q.pop();vis[u] = false;for(int i = head[u]; i != -1; i = edge[i].next){Edge E = edge[i];if(dist[E.to] > dist[u] + E.val){dist[E.to] = dist[u] + E.val;if(!vis[E.to]){vis[E.to] = true;used[E.to]++;if(used[E.to] > N)//存在负环 {printf("-1\n");return ;}Q.push(E.to);}}} }printf("%d\n", dist[e]);}int main(){int k = 1;int t;scanf("%d", &t);while(t--){scanf("%d%d", &N, &D);init();getMap();printf("Case %d: ", k++);SPFA(sx, ex);}return 0;}


AC代码:
0 0
原创粉丝点击