"Help Jimmy" 是在下圖所示的場景上完成的游戲。
場景中包括多個長度和高度各不相同的平臺。地面是最低的平臺,高度為零,長度無限。
Jimmy老鼠在時刻0從高于所有平臺的某處開始下落,它的下落速度始終為1米/秒。當Jimmy落到某個平臺上時,游戲者選擇讓它向左還是向右
跑,它跑動的速度也是1米/秒。當Jimmy跑到平臺的邊緣時,開始繼續(xù)下落。Jimmy每次下落的高度不能超過MAX米,不然就會摔死,游戲也會結束。
設計一個程序,計算Jimmy到底地面時可能的最早時間。
Input
第一行是測試數(shù)據(jù)
的組數(shù)t(0 <= t <=
20)。每組測試數(shù)據(jù)的第一行是四個整數(shù)N,X,Y,MAX,用空格分隔。N是平臺的數(shù)目(不包括地面),X和Y是Jimmy開始下落的位置的橫豎坐
標,MAX是一次下落的最大高度。接下來的N行每行描述一個平臺,包括三個整數(shù),X1[i],X2[i]和H[i]。H[i]表示平臺的高度,X1[i]
和X2[i]表示平臺左右端點的橫坐標。1 <= N <= 1000,-20000 <= X, X1[i], X2[i]
<= 20000,0 < H[i] < Y <= 20000(i = 1..N)。所有坐標的單位都是米。
Jimmy的大小和平臺的厚度均忽略不計。如果Jimmy恰好落在某個平臺的邊緣,被視為落在平臺上。所有的平臺均不重疊或相連。測試數(shù)據(jù)保證問題一定有解。
Output
對輸入的每組測試數(shù)據(jù),輸出一個整數(shù),Jimmy到底地面時可能的最早時間。
Sample Input
1
3 8 17 20
0 10 8
0 10 13
4 14 3
Sample Output
23
解法是這樣
按照y坐標給每個區(qū)間排序,以線段端點為節(jié)點構圖,每個節(jié)點最多有2條邊,用線段樹維護當前線段端點下方的線段。最后求最長路就可以了。
原來想簡化,不要創(chuàng)建s和e節(jié)點,結果反而悲劇,各種漏考慮情況。。以后這類題目還是謹慎點吧。。
1 # include <cstdio>
2 # include <algorithm>
3 # include <cstring>
4 # define mid(p) ((st[p].s+st[p].e)>>1)
5 # define abs(a) ((a)>0?(a):-(a))
6 using namespace std;
7 const int N=150000;
8 int g[2005],nxt[5005],val[5005],v[5005],c,len[2005];
9 struct
10 {
11 int s,e,id;
12 }st[N];
13 struct node
14 {
15 int h,s,e;
16 }data[1005];
17 int solve(int pos)
18 {
19 if(len[pos]!=-1) return len[pos];
20 else
21 {
22 if(g[pos]==-1) return pos?0xfffffff:0;
23 else
24 {
25 len[pos]=0xfffffff;
26 for(int p=g[pos];p!=-1;p=nxt[p])
27 {
28 len[pos]=min(len[pos],solve(v[p])+val[p]);
29 }
30 return len[pos];
31 }
32 }
33 }
34 bool cmp(const node &a,const node &b)
35 {
36 return a.h<b.h;
37 }
38 void init(int s,int e,int pos=1)
39 {
40 st[pos].s=s;
41 st[pos].e=e;
42 st[pos].id=-1;
43 if(e!=s+1)
44 {
45 init(s,mid(pos),pos<<1);
46 init(mid(pos),e,(pos<<1)+1);
47 }
48 }
49 int get(int target,int pos=1)
50 {
51 if(st[pos].id!=-1) return st[pos].id;
52 else if(target>=mid(pos)) return get(target,(pos<<1)+1);
53 else return get(target,(pos<<1));
54 }
55 void insert(int s,int e,int id,int pos=1)
56 {
57 if(st[pos].s==s&&st[pos].e==e)
58 st[pos].id=id;
59 else
60 {
61 if(st[pos].id!=-1)
62 {
63 st[pos<<1].id=st[(pos<<1)+1].id=st[pos].id;
64 st[pos].id=-1;
65 }
66 if(s>=mid(pos)) insert(s,e,id,(pos<<1)+1);
67 else if(e<=mid(pos)) insert(s,e,id,pos<<1);
68 else
69 {
70 insert(s,mid(pos),id,pos<<1);
71 insert(mid(pos),e,id,(pos<<1)+1);
72 }
73 }
74 }
75 inline void addedge(int s,int e,int len)
76 {
77 v[c]=e;
78 val[c]=len;
79 nxt[c]=g[s];
80 g[s]=c++;
81 }
82 int main()
83 {
84 int test;
85 scanf("%d",&test);
86 while(test--)
87 {
88 int n,x,y,maxnum;
89 scanf("%d%d%d%d",&n,&x,&y,&maxnum);
90 for(int i=1;i<=n;i++)
91 {
92 scanf("%d%d%d",&data[i].s,&data[i].e,&data[i].h);
93 data[i].s+=20000;
94 data[i].e+=20000;
95 }
96 x+=20000;
97 data[0].h=0;
98 sort(data+1,data+n+1,cmp);
99 init(0,40001);
100 insert(0,40001,0);
101 memset(g,-1,sizeof(g));
102 c=0;
103 for(int i=1;i<=n;i++)
104 {
105 int p=get(data[i].s);
106 if(data[i].h-data[p].h<=maxnum)
107 {
108 addedge(2*i-1,p?2*p-1:0,p?abs(data[i].s-data[p].s):0);
109 addedge(2*i-1,p?2*p:0,p?abs(data[i].s-data[p].e):0);
110 }
111 p=get(data[i].e);
112 if(data[i].h-data[p].h<=maxnum)
113 {
114 addedge(2*i,p?2*p-1:0,p?abs(data[i].e-data[p].s):0);
115 addedge(2*i,p?2*p:0,p?abs(data[i].e-data[p].e):0);
116 }
117 insert(data[i].s,data[i].e+1,i);
118 }
119 {
120 int p=get(x);
121 addedge(2*n+1,p?2*p-1:0,p?abs(x-data[p].s):0);
122 addedge(2*n+1,p?2*p:0,p?abs(x-data[p].e):0);
123 }
124 memset(len,-1,sizeof(len));
125 printf("%d\n",y+solve(2*n+1));
126 }
127 return 0;
128 }
129