#include <iostream> #include <vector> #include <algorithm> #include <cstring> using namespace std; const int MAXLEN = 2000; const int INFINIT = 1000000; struct Platform { int Lx; int Rx; int h; }; vector<Platform> platforms; int LeftMinTime[MAXLEN]; int RightMinTime[MAXLEN]; int n,x,y,imax; //递归求解 int MinTime(int L,bool bLeft) { int y=platforms[L].h; int x; if(bLeft) x=platforms[L].Lx; else x=platforms[L].Rx; int i; for(i = L + 1; i <= n; i++) if(x >= platforms[i].Lx && x <= platforms[i].Rx) break; if(i <= n) { if(y - platforms[i].h > imax) return INFINIT; } else { if(y > imax) return INFINIT; else return y; } int iLeftTime = y - platforms[i].h + x - platforms[i].Lx; int iRighttime = y - platforms[i].h + platforms[i].Rx - x; if(LeftMinTime[i] == -1) LeftMinTime[i] = MinTime(i, true); if(RightMinTime[i] == -1) RightMinTime[i] = MinTime(i, false); iLeftTime += LeftMinTime[i]; iRighttime += RightMinTime[i]; if(iLeftTime > iRighttime) return iRighttime; return iLeftTime; } //for cmpare bool cmpare(const Platform & v1, const Platform & v2) { return v1.h>v2.h; } int main() { int t; while(cin>>t && (t >= 0 && t <= 20)) { for(int i = 0; i < t; i++) { memset(LeftMinTime, -1, sizeof(LeftMinTime)); memset(RightMinTime, -1, sizeof(RightMinTime)); cin>>n>>x>>y>>imax; Platform temp; temp.Lx = x; temp.Rx = x; temp.h = y; platforms.push_back(temp); for(int j = 0; j<n; j++) { cin>>temp.Lx>>temp.Rx>>temp.h; platforms.push_back(temp); } sort(platforms.begin(),platforms.end(), cmpare); cout<<MinTime(0,true)<<endl; platforms.erase(platforms.begin(),platforms.end()); } } return 0; } /* 解题报告: 1、个人认为动态规划较难题,状态转移不容易找,找着后也不容易写出代码 2、可以这样思考这道题,其子问题是从板的左边到地面的最短时间和从板的右端到地面的最 短时间,为此可以为板编号,从上到下编号,其中小球的编程为0,这样依次编下去, 在同一高度编号前后无所谓,于是该题的状态是木板的编号,值为从该板的左端到地面和 板的右端到地面的最短时间。 3、注意的地方是在用vector时不要忘了在最后用下erase方法,对其进行清空 */