题意就不描述了。
将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; }