题意就不描述了。
将Jimmy开始下落的地方也看成一个平台,平台的左右坐标相同;为了便于处理,把地面也看成了一个平台。
用dp[ i ][ 0 ]表示到达第 i 个平台左边的最少时间,dp[ i ][ 1 ] 表示到达第 i 个平台右边的最少时间。
状态转移方程:
从第 i 个平台左边到第 j 个平台左边:dp[ j ][ 0 ] = MIN( dp[ j ][ 0 ], dp[ i ][ 0 ] + plat[ i ].h - plat[ j ].h + plat[ i ].xl - plat[ j ].xl );
从第 i 个平台左边到第 j 个平台右边:dp[ j ][ 1 ] = MIN( dp[ j ][ 1 ], dp[ i ][ 0 ] + plat[ i ].h - plat[ j ].h + plat[ j ].xr - plat[ i ].xl );
从第 i 个平台右边到第 k 个平台左边:dp[ k ][ 0 ] = MIN( dp[ k ][ 0 ], dp[ i ][ 1 ] + plat[ i ].h - plat[ k ].h + plat[ i ].xr - plat[ k ].xl );
从第 i 个平台右边到第 k 个平台右边:dp[ k ][ 1 ] = MIN( dp[ k ][ 1 ], dp[ i ][ 1 ] + plat[ i ].h - plat[ k ].h + plat[ k ].xr - plat[ k ].xr );
从第 i 个平台的左右下落,不一定落到同一个平台上。
将平台排序,记录每个平台后面的一个平台。
#include <iostream>
#include <algorithm>
using namespace std;
#define N 1005
int dp[N][2], next[N][2]; //next记录每个平台的左右端下面的平台号
struct plat
{
int xl, xr, h; //平台左右坐标及高度
} p[N];
int compare(const plat &a, const plat &b)
{
return a.h > b.h;
}
void getNext(int n) //求next数组
{
int i, j;
bool mark1, mark2;
for(i = 0; i <= n; i++){
mark1 = mark2 = false;
for(j = i+1; j <= n+1; j++){
if(!mark1 && p[i].xl >= p[j].xl && p[i].xl <= p[j].xr){
next[i][0] = j;
mark1 = true;
}
if(!mark2 && p[i].xr >= p[j].xl && p[i].xr <= p[j].xr){
next[i][1] = j;
mark2 = true;
}
if(mark1 && mark2) break;
}
}
}
inline int MIN(int a, int b)
{
return a > b ? b : a;
}
int main()
{
int t, i, j, k;
int n, x, y, max;
int h1, h2;
scanf("%d", &t);
while(t--)
{
scanf("%d%d%d%d", &n, &x, &y, &max);
p[0].xl = p[0].xr = x; //将初始位置处看成一个平台
p[0].h = y;
for(i = 1; i <= n; i++)
scanf("%d%d%d", &p[i].xl, &p[i].xr, &p[i].h);
p[n+1].xl = -30000; //将地面看成一个平台
p[n+1].xr = 30000;
p[n+1].h = 0;
sort(p+1, p+n+1, compare); //对中间的平台排序
getNext( n );
for(i = 1; i <= n+1; i++){ //初始化
for(j = 0; j < 2; j++)
dp[i][j] = 1000000;
}
dp[0][0] = dp[0][1] = 0;
for(i = 0; i <= n; i++){
j = next[i][0]; //取当前平台左端的下面一个平台
k = next[i][1]; //取当前平台右端的下面一个平台
h1 = p[i].h - p[j].h;
h2 = p[i].h - p[k].h;
if(h1 <= max){ //判断
if(j == n+1) //对于地面,直接落地即可,不用继续走到左右端
dp[n+1][0] = MIN(dp[n+1][0], dp[i][0] + h1);
else {
dp[j][0] = MIN(dp[j][0], dp[i][0] + h1 + p[i].xl - p[j].xl);
dp[j][1] = MIN(dp[j][1], dp[i][0] + h1 + p[j].xr - p[i].xl);
}
}
if(h2 <= max){
if(k == n+1)
dp[n+1][0] = MIN(dp[n+1][0], dp[i][1] + h2);
else {
dp[k][0] = MIN(dp[k][0], dp[i][1] + h2 + p[i].xr - p[k].xl);
dp[k][1] = MIN(dp[k][1], dp[i][1] + h2 + p[k].xr - p[i].xr);
}
}
}
printf("%d\n", dp[n+1][0]);
}
return 0;
}