将给定的平台按照高度依次排序,每一个平台都有向左的时间和向右的时间,当然并不是时间最短的就一定是最优,因为如果某一个方向下的平台高度超过规定高度则是不可行的方向。这样从小鼠出发点开始自上往下按层次寻找每个平台的最优时间,先查找该平台的某方向是否可行,可行则选取最短时间,否则该路不通(即设置最大值),dp[i][k]表示第i平台方向k的最短时间,不难得出转移方程dp[i][k]=min(dp[j][0]+s[i].h-s[j].h+s[i].x[k]-s[j].x[0],dp[j][1]+s[i].h-s[j].h+s[j].x[1]-s[i].x[k]),具体思路见注释:
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int INF=(1<<30);
struct platform
{
int x[2],h;
void setValue(int a,int b,int c)
{
x[0]=a;
x[1]=b;
h=c;
}
bool operator < (const platform a)const
{
return h>a.h; //高的在前
}
}s[1010];
int dp[1010][2];
int main()
{
ios::sync_with_stdio(false);
int t;
cin>>t;
while(t--)
{
memset(dp,0,sizeof(dp));
int n,x,y,maxn;
cin>>n>>x>>y>>maxn;
s[0].setValue(x,x,y); //将小鼠位置初始化(算作一个平台)
for(int i=1;i<=n;i++)
cin>>s[i].x[0]>>s[i].x[1]>>s[i].h;
sort(s,s+n+1); //这里一开始少排了一个,无限WA。。。一定记住这是n+1个元素。。。
dp[n][0]=dp[n][1]=s[n].h; //最下面的平台的最短时间为此平台高度
for(int i=n-1,j;i>=0;i--)
{
for(int k=0;k<2;k++)
{
for(j=i+1;j<=n;j++) //向下检查该平台某一端下是否有平台(k=0表示左,k=1表示右)
if(s[i].x[k]>=s[j].x[0]&&s[i].x[k]<=s[j].x[1])
break;
if(j<=n) //如果某端点下有平台
{
if(s[i].h-s[j].h>maxn) //如果差值超过限定高度
dp[i][k]=INF; //设置一个很大的数
else //否则选取最小时间
dp[i][k]=min(dp[j][0]+s[i].h-s[j].h+s[i].x[k]-s[j].x[0],dp[j][1]+s[i].h-s[j].h+s[j].x[1]-s[i].x[k]);
}
else //如果没有平台,则说明可直接通过该端到达地面
{
if(s[i].h>maxn) //如果到地面距离超过限定
dp[i][k]=INF;
else //可以安全到达地面
dp[i][k]=s[i].h;
}
}
}
cout<<dp[0][0]<<endl;
}
return 0;
}