中问题不再解释
dp[i][0]表示下落到第i个平台的最左端需要的最少时间
dp[i][1]表示下落到第i个平台的最右端需要的最少时间
把起始点和地面也作为一个平面
#include "stdio.h"
#include "string.h"
#include "algorithm"
using namespace std;
const int inf=0x3f3f3f3f;
struct Mark
{
int l,r,h;
}mark[1010];
bool cmp(Mark a,Mark b)
{
return a.h>b.h;
}
int Min(int a,int b)
{
if (a<b) return a;
else return b;
}
int main()
{
int T,n,i,j,flag1,flag2,ans,maxy;
int dp[1010][2];
scanf("%d",&T);
while (T--)
{
scanf("%d%d%d%d",&n,&mark[0].l,&mark[0].h,&maxy);
ans=inf;
mark[0].r=mark[0].l;
memset(dp,inf,sizeof(dp));
for (i=1;i<=n;i++)
scanf("%d%d%d",&mark[i].l,&mark[i].r,&mark[i].h);
sort(mark,mark+n+1,cmp);
mark[n+1].l=-20000;
mark[n+1].r=20000;
mark[n+1].h=0;
dp[0][0]=dp[0][1]=0;
for (i=0;i<=n;i++)
{
flag1=flag2=0;
for (j=i+1;j<=n+1;j++)
{
if (flag1+flag2==2 || mark[i].h-mark[j].h>maxy) break;
if (flag1==0 && mark[i].l>=mark[j].l && mark[i].l<=mark[j].r && mark[i].h!=mark[j].h)// 从i平台的左端掉落到j平台
{
flag1=1;
if (j==n+1)
ans=Min(ans,dp[i][0]); // 掉落到地面时特殊处理
else
{
dp[j][0]=Min(dp[j][0],dp[i][0]+mark[i].l-mark[j].l); // 到j平面左端
dp[j][1]=Min(dp[j][1],dp[i][0]+mark[j].r-mark[i].l); // 到j平面右端
}
}
if (flag2==0 && mark[i].r>=mark[j].l && mark[i].r<=mark[j].r && mark[i].h!=mark[j].h) //从i平面的右端掉落到j平面
{
flag2=1;
if (j==n+1)
ans=Min(ans,dp[i][1]);
else
{
dp[j][0]=Min(dp[j][0],dp[i][1]+mark[i].r-mark[j].l);
dp[j][1]=Min(dp[j][1],dp[i][1]+mark[j].r-mark[i].r);
}
}
}
}
printf("%d\n",ans+mark[0].h);
}
return 0;
}