从下向上倒推,dp[i][0]表示从第j块板子到第i块板子的左边的最小路程,dp[i][1]表示从第j块板子到第i块板子的右边的最小路程,
先从小到大给板子排序,如果当前第i块板子下面有第j块板子的话,则比较从当前 第j块板子的左右分别到第i块板子的左右最小路程
有点细节要注意 ,首先要倒推到起始点,就是人落下的点,所以要多记录一个"人"板子,然后应该初始化DP为一个较大值,因为你第j块板子如果有一端不能达到i则就要给他一个极大值
#include <iostream>
#include <algorithm>
using namespace std;
struct Ban
{
int x, y, h;
}ban[1100];
int dp[1100][2];
bool cmp(Ban a, Ban b)
{
return a.h < b.h;
}
int main()
{
//freopen("IN.txt", "r", stdin);
//freopen("OUT.txt", "w", stdout);
int t;
scanf("%d", &t);
while (t --){
int n, sx, sy, h;
scanf("%d%d%d%d", &n, &sx, &sy, &h);
for (int i = 1; i <= n; i ++){
scanf("%d%d%d", &ban[i].x, &ban[i].y, &ban[i].h);
}
ban[n+1].x = sx, ban[n+1].y = sx, ban[n+1].h = sy;
sort(ban+1, ban+1+n, cmp);
//memset(dp, , sizeof(dp));
bool check1, check2;
dp[0][0] = dp[0][1] = 0;
for (int i = 1; i <= n+1; i ++){
check1 = check2 = false;
dp[i][0] = dp[i][1] = 0xffffff;
for (int j = i-1; j >= 0; j --){
if (ban[i].h - ban[j].h > h || (check1 && check2))break;
if (!check1){
if (!j)dp[i][0] = 0;
else
if (ban[j].y >= ban[i].x && ban[i].x >= ban[j].x){
dp[i][0] = min(dp[j][1]+(ban[j].y - ban[i].x), dp[j][0]+(ban[i].x-ban[j].x));
check1 = true;
}
}
if (!check2){
if (!j)dp[i][1] = 0;
else
if (ban[j].x <= ban[i].y && ban[j].y >= ban[i].y){
dp[i][1] = min(dp[j][0]+(ban[i].y-ban[j].x), dp[j][1]+(ban[j].y-ban[i].y));
check2 = true;
}
}
}
}
//
printf("%d\n", dp[n+1][0]+sy);
}
return 0;
}