EOJ:The Ninja Way

The Ninja Way

Time Limit: 3000MS Memory Limit: 65536K

Description

As we all know, Ninjas travel by jumping from treetop to treetop. A clan of Ninjas plans to use N trees to hone their tree hopping skills. They will start at the shortest tree and make N-1 jumps, with each jump taking them to a taller tree than the one they‟re jumping from. When finished, they will have been on every tree exactly once, traversing them in increasing order of height, and ending up on the tallest tree.
The ninjas can travel for at most a certain horizontal distance D in a single jump. To make this as much fun as possible, the Ninjas want to maximize the distance between the positions of the shortest tree and the tallest tree.

The ninjas are going to plant the trees subject to the following constraints.
  • All trees are to be planted along a one-dimensional path.
  • Trees must be planted at integer locations along the path, with no two trees at the same location.
  • Trees must be arranged so their planted 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.
  • The Ninjas can only jump so far, so every tree must be planted close enough to the next taller tree. Specifically, they must be no further than D apart on the ground (the difference in their heights doesn't matter).

Given N trees, in a specified order, each with a distinct integer height, help the ninjas figure out the maximum possible distance they can put between the shortest tree and the tallest tree, and be able to use the trees for training.

 

Input

There will be multiple test cases. Each test case begins with a line containing two integers N (1 ≤ N ≤ 1000) and D (1 ≤ D ≤10^6). The next N lines each contain a single integer, giving the heights of the N trees, in the order that they should be planted. Within a test case, all heights will be unique. The last test case is followed by a line with two 0's.

 

Output

For each test case, output a line with a single integer representing the maximum distance between the shortest and tallest tree, subject to the constraints above, or -1 if it is impossible to lay out the trees. Do not print any blank lines between answers.

 

Sample Input

4 4
20
30
10
40
5 6
20
34
54
10
15
4 2
10
20
16
13
0 0

Sample Output

3
3
-1
原题地址:http://www.cn210.com/onlinejudge/problemshow.php?pro_id=238
_____________________________________________________________________________________________________
题解:
一开始以为是贪心模拟,不过比赛中没时间做。
后来问了才知道是差分约束,虽说学最短路的时候看过差分约束,但是从来没做过,这道就算第一道差分约束吧。
设第一棵树为X1,第二棵为X2……
由题可知,X1-X2<0,由于差分约束要取等号,这里我们写成X1-X2<=-1,所以X2连一条-1的边到X1,其他依次类推
Xi-Xi-1<=D(第i大的树和第i-1大的树),所以Xi连一条D的边到Xi-1。

要注意,这是在最矮的树在最高的数左侧的情况
当最高的树在最低的树的右边时,我们得到的结果是正的,而其在左边时,我们得到的结果是负的。那么那个负的值怎么处理呢?取绝对值吗?当然不是。如果理解了差分约束的原理,我们可以看出我们求出的最高的树的最短路的值,是在最低树放在数轴原点的时候,最高的树在数轴所能摆放的最大值。当最高树在最低树右边时,就是符合题目要求的最远距离,而最高树在其左边时,却是离原点的最近距离。所以,求解此题时,要先判断最高树和最低树的位置关系,若最高树在最低树的左边,我们要把所有树逆序排列来求解。

然后做遍最短路,用SPFA,因为dij不能处理负边负环。
若源点为Xn,则DIST[I]表示Xi+dist[i]<=Xn

中途wa了好多次,先是数组开小了,后来max也小了……


代码
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<memory.h>
4  #define maxn 1003
5  #define maxm 50003
6  #define oo 1000000000
7  int n,d,i,j,s,t,num;
8  int head[maxn];
9 int next[maxm],node[maxm];
10 int q[500000],sum[maxn],vis[maxn];
11 long long dist[maxn],ew[maxm],ans;
12 struct node
13 {
14 int x,y;
15 }tree[maxn];
16 long long spfa(int start,int end)
17 {
18 int h,t,i,v,u;
19 h=1;t=1;
20 q[1]=start;
21 for (i=1;i<=n;i++)
22 dist[i]=oo;
23 memset(sum,0,sizeof(sum));
24 memset(vis,0,sizeof(vis));
25 dist[start]=0;
26 sum[start]=1;
27 vis[start]=1;
28 while (h<=t)
29 {
30 u=q[h];
31 for (i=head[u];i;i=next[i])
32 {
33 v=node[i];
34 if (dist[v]>dist[u]+ew[i])
35 {
36 dist[v]=dist[u]+ew[i];
37 if (vis[v]==0)
38 {
39 q[++t]=v;
40 vis[v]=1;
41 }
42 sum[v]++;
43 if (sum[v]>n) return -1;
44 }
45 }
46 vis[u]=0;
47 h++;
48 }
49 return dist[end];
50 }
51 int cmp(const void *a,const void *b)
52 {
53 struct node *va=(struct node*)a;
54 struct node *vb=(struct node*)b;
55 return va->x-vb->x;
56 }
57 void creat(int u,int v,int w)
58 {
59 next[++num]=head[u];
60 head[u]=num;
61 node[num]=v;
62 ew[num]=w;
63 }
64 int main()
65 {
66 while (scanf("%d%d",&n,&d)!=EOF)
67 {
68 if (n==0&&d==0) break;
69 num=0;
70 memset(head,0,sizeof(head));
71 memset(next,0,sizeof(next));
72 for (i=1;i<=n;i++)
73 {
74 scanf("%d",&tree[i].x);
75 tree[i].y=i;
76 }
77 qsort(tree+1,n,sizeof(tree[1]),cmp);
78 if (tree[1].y<tree[n].y)
79 {
80 for (i=1;i<n;i++)
81 {
82 creat(tree[i].y,tree[i+1].y,d);
83 creat(tree[i+1].y,tree[i].y,d);
84 }
85 for (i=1;i<n;i++)
86 creat(i+1,i,-1);
87 s=tree[1].y;t=tree[n].y;
88 }
89 else
90 {
91 for (i=n;i>1;i--)
92 {
93 creat(n-tree[i-1].y+1,n-tree[i].y+1,d);
94 creat(n-tree[i].y+1,n-tree[i-1].y+1,d);
95 }
96 for (i=1;i<n;i++)
97 creat(i+1,i,-1);
98 s=n-tree[1].y+1;t=n-tree[n].y+1;
99 }
100 ans=spfa(s,t);
101 if (ans<0) printf("-1\n");
102 else
103 printf("%lld\n",ans);
104 }
105 return 0;
106 }

posted on 2010-08-07 15:22  风也轻云也淡  阅读(199)  评论(0编辑  收藏  举报