简单DP,每一条线段记录两个值,到左端点最少时间与到又端点最少时间。按照这个往后推导。
#include<cstdio> #include<cstring> #include<cmath> #include<stack> #include<vector> #include<string> #include<iostream> #include<algorithm> using namespace std; const int maxn=1000+10; int T; int N,X,Y,MAX; struct W { int x1,x2,h; } s[maxn]; int dpLeft[maxn],dpRight[maxn]; bool cmp(const W&a,const W&b) { return a.h>b.h; } int main() { scanf("%d",&T); while(T--) { scanf("%d%d%d%d",&N,&X,&Y,&MAX); s[0].x1=X,s[0].x2=X,s[0].h=Y; for(int i=1; i<=N; i++) scanf("%d%d%d",&s[i].x1,&s[i].x2,&s[i].h); s[N+1].x1=-0x7fffffff,s[N+1].x2=0x7FFFFFFF,s[N+1].h=0; for(int i=0; i<=N+1; i++) dpRight[i]=dpLeft[i]=0x7fffffff; sort(s+1,s+N+1,cmp); dpLeft[0]=0,dpRight[0]=0; int ans=0x7FFFFFFF; for(int i=0; i<=N; i++) { //从左端下落 if(dpLeft[i]!=0x7fffffff) { for(int j=i+1; j<=N+1; j++) { if(s[j].x1<=s[i].x1&&s[i].x1<=s[j].x2) { if(s[i].h-s[j].h<=MAX) { if(j==N+1) { int cost=dpLeft[i]+s[i].h-s[j].h; ans=min(ans,cost); } else { int cost; //到左端需要的时间 cost=dpLeft[i]+s[i].h-s[j].h+s[i].x1-s[j].x1; dpLeft[j]=min(cost,dpLeft[j]); //到右端需要的时间 cost=dpLeft[i]+s[i].h-s[j].h+s[j].x2-s[i].x1; dpRight[j]=min(cost,dpRight[j]); } } break; } } } //往右跑 if(dpRight[i]!=0x7fffffff) { for(int j=i+1; j<=N+1; j++) { if(s[j].x1<=s[i].x2&&s[i].x2<=s[j].x2) { if(s[i].h-s[j].h<=MAX) { if(j==N+1) { int cost=dpRight[i]+s[i].h-s[j].h; ans=min(ans,cost); } else { int cost; //到左端需要的时间 cost=dpRight[i]+s[i].h-s[j].h+s[i].x2-s[j].x1; dpLeft[j]=min(cost,dpLeft[j]); //到右端需要的时间 cost=dpRight[i]+s[i].h-s[j].h+s[j].x2-s[i].x2; dpRight[j]=min(cost,dpRight[j]); } } break; } } } } printf("%d ",ans); } return 0; }