題意:

兩個人爬山,時刻要保證在同一水平面上,直到兩人互換位置。問走過的最短距離。兩點間距離定義為兩點間的y軸絕對值差。
給力條件:除了首尾兩點每個點的y坐標均不相同
解法:
DP?殺雞用牛刀,沒必要!
貪心!
首先明確,不能走回頭路,這里的回頭路指完全退回到上個步驟所在的點,顯然,這樣的走法是無意義的。
設置兩個指針,p1指向頭,p2指向尾,循環至兩個指針重疊。下面具體分四種情況討論:
1、如果y
p1+1>y
p1且y
p2-1>y
p2,這種情況下當然山峰高的幫助山峰低的越過低的山峰
2、如果y
p1+1>y
p1且y
p2-1<y
p2,這種情況又要分兩種情況:
2.1 如果(p1,p1+1)這段上坡通過局部回退能夠讓p2度過這個山谷,顯然這樣就是p2--
2.2 否則p1必須回退至上個拐點,試圖獲得更低的高度,這樣就是p1--
3、如果y
p1+1<y
p1且y
p2-1>y
p2,與上種情況類似,不加贅述。
4、如果y
p1+1<y
p1且y
p2-1<y
p2,這種情況不應該是正常情況下應該出現的,因該是碰到某個很深的山谷后上坡段回退形成的,這時候應該繼續后退,以尋求更低點。
代碼里寫的很清楚,大家看代碼吧:
1
# include <cstdio>
2
using namespace std;
3
# define min(a,b) ((a)<(b)?(a):(b))
4
# define max(a,b) ((a)>(b)?(a):(b))
5
int p[1001][2],n,p1,p2,ans,last;
6
int main()
7

{
8
int test;
9
scanf("%d",&test);
10
while(test--)
11
{
12
scanf("%d",&n);
13
for(int i=0;i<n;i++)
14
scanf("%d %d",&p[i][0],&p[i][1]);
15
p1=0,p2=n-1,ans=0;
16
last=p[0][1];
17
while(p2>p1)
18
{
19
if(p[p2-1][1]>p[p2][1]&&p[p1+1][1]>p[p1][1])
20
{
21
ans+=2*(min(p[p2-1][1],p[p1+1][1])-last);
22
last=min(p[p2-1][1],p[p1+1][1]);
23
if(p[p2-1][1]==last) p2--;
24
if(p[p1+1][1]==last) p1++;
25
}
26
else if(p[p2-1][1]<p[p2][1]&&p[p1+1][1]>p[p1][1])
27
{
28
ans+=2*(last-max(p[p2-1][1],p[p1][1]));
29
last=max(p[p2-1][1],p[p1][1]);
30
if(last==p[p2-1][1]) p2--;
31
else p1--;
32
}
33
else if(p[p2-1][1]>p[p2][1]&&p[p1+1][1]<p[p1][1])
34
{
35
ans+=2*(last-max(p[p2][1],p[p1+1][1]));
36
last=max(p[p2][1],p[p1+1][1]);
37
if(last==p[p1+1][1]) p1++;
38
else p2++;
39
}
40
else
41
{
42
ans+=2*(min(p[p1][1],p[p2][1])-last);
43
last=min(p[p1][1],p[p2][1]);
44
if(last==p[p1][1]) p1--;
45
else p2++;
46
}
47
}
48
printf("%d\n",ans*2);
49
}
50
return 0;
51
}
52