dp首先要确定状态。
竖直方向所用时间是一定的,可以最后直接加Y。
刚开始想的是从高到低,发现这样无法确定状态。
从上往下,每一个平面有可能从上面多个平面推出。
而从下往上,一个平面只能从下面一个平面推出。
将0,Y都变成一个平面。
原问题 从第0层到n+1层的时间。
子问题 从第i层到n+1层的时间。
因为同一层有左右两个状态,所以需要二维数组。
状态:dp[i][0], 从i层左边到地面所用最短时间。
dp[i][1] 从i层右边到地面所用最短时间。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define inf 0x3f3f3f3f
using namespace std;
struct node{
int x1,x2,y;
}ns[1100];
bool cmp(node a,node b)
{
return a.y<b.y;
}
int dp[1100][2];
int main()
{
int t;
cin>>t;
while(t--)
{
int n,X,Y,maxn;
scanf("%d%d%d%d",&n,&X,&Y,&maxn);
for(int i=1;i<=n;i++)
{
scanf("%d%d%d",&ns[i].x1,&ns[i].x2,&ns[i].y);
}
ns[0].x1=X,ns[0].x2=X,ns[0].y=Y;
ns[n+1].x1=-20000,ns[n+1].x2=20000,ns[n+1].y=0;
sort(ns,ns+n+2,cmp);
memset(dp,inf,sizeof(dp));
dp[0][0]=dp[0][1]=0;
for(int i=1;i<=n+1;i++)
{
for(int j=i-1;j>=0&&ns[i].y-ns[j].y<=maxn;j--)
{
if(ns[j].x1<=ns[i].x1&&ns[i].x1<=ns[j].x2)
{
if(j==0)
{
dp[i][0]=0;
}
else dp[i][0]=min(dp[j][0]+ns[i].x1-ns[j].x1,dp[j][1]+ns[j].x2-ns[i].x1);
break;//只能到达下面最高的满足条件的平面。
//两个break 不是同时满足,所以dp[i][0]和dp[i][1]需要分开求。
}
}
for(int j=i-1;j>=0&&ns[i].y-ns[j].y<=maxn;j--)
{
if(ns[j].x1<=ns[i].x2&&ns[i].x2<=ns[j].x2)
{
if(j==0)
{
dp[i][1]=0;
}
else
{
dp[i][1]=min(dp[j][0]+ns[i].x2-ns[j].x1,dp[j][1]+ns[j].x2-ns[i].x2);
}
break;
}
}
}
printf("%d\n",min(dp[n+1][1],dp[n+1][0])+Y);
}
}