http://poj.org/problem?id=1661
题意:不多讲,求从出发点到底的最短时间。
思路:把从一个点到下一个板的问题看成两个雷同的问题,一切尽在代码解释中。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define M 1000
#define inf 0x3f3f3f3f
using namespace std;
int aLeftMinTime[M+10]; //记录左点到底的最短时间
int aRightMinTime[M+10]; //记录右点到底的最短时间
int n,x,y,Max;
class Platform
{
public:
int Lx,Rx,h; //记录端点和高度
}platform[M+10];
int cmp(Platform a,Platform b) //按高度进行排序
{
return a.h > b.h;
}
int MinTime(int L,bool bLeft) //分成两个子问题,从左点和从右点
{ //bLeft是区别左右
int y = platform[L].h;
int x;
if(bLeft)
x = platform[L].Lx;
else
x = platform[L].Rx;
int i;
for(i = L + 1;i <= n; i++) //找出下面有没有线段可以落地
if(platform[i].Lx <= x && platform[i].Rx >= x)
break;
if(i <= n){ //如果有则分成两种情况,一是可以跳,二是不可以
if(y - platform[i].h > Max)
return inf;
}
else { //如果没有线段则看是否能直接跳到底
if(y > Max)
return inf;
else
return y;
}
int nLeftMinTime = y - platform[i].h + x - platform[i].Lx; //到下一个线段左点需要的时间
int nRightMinTime = y - platform[i].h + platform[i].Rx - x; //到下一个线段右点需要的时间
//这是分成两个子问题,结果是取时间最短的
if(aLeftMinTime[i] == -1) //判断是否走过,优化
aLeftMinTime[i] = MinTime(i,true);
if(aRightMinTime[i] == -1)
aRightMinTime[i] = MinTime(i,false);
nLeftMinTime += aLeftMinTime[i];
nRightMinTime += aRightMinTime[i];
if(nLeftMinTime < nRightMinTime)
return nLeftMinTime;
return nRightMinTime;
}
int main()
{
// freopen("in.txt","r",stdin);
int t;
scanf("%d",&t);
while(t--){
memset(aLeftMinTime,-1,sizeof(aLeftMinTime));
memset(aRightMinTime,-1,sizeof(aRightMinTime));
scanf("%d%d%d%d",&n,&x,&y,&Max);
platform[0].Lx = x;
platform[0].Rx = x;
platform[0].h = y;
for(int i = 1;i <= n; i++)
scanf("%d%d%d",&platform[i].Lx,&platform[i].Rx,&platform[i].h);
sort(platform,platform+n+1,cmp);
printf("%d\n",MinTime(0,true));
}
return 0;
}