http://poj.org/problem?id=1661
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAX_N 1000
#define INFINITE 1000000
int t, n, x, y, max_h;
struct Platform{
int Lx, Rx, h;
bool operator < (const Platform& b) const
{
return h > b.h;
}
};
//int MyCompare( const void * e1, const void * e2 )
//{
// Platform * p1, * p2;
// p1 = (Platform * ) e1;
// p2 = (Platform * ) e2;
// return p2->h - p1->h;
//}
Platform aPlatform[MAX_N + 10];
int aLeftMinTime[MAX_N + 10];
int aRightMinTime[MAX_N + 10];
/*
1
3 8 17 20
0 10 8
0 10 13
4 14 3
*/
int MinTime(int L, bool left)
{
int y = aPlatform[L].h;
int x;
if(left)
x=aPlatform[L].Lx;
else
x=aPlatform[L].Rx;
//检查是否L底下有平台
int j=-1;
for(int i=L+1;i<=n;i++)
{
if(aPlatform[i].Lx<=x && x<=aPlatform[i].Rx )
{
j=i;
break;
}
}
if(j==-1)//底下没平台
if(y > max_h)
return INFINITE;
else
return y;
// 有平台的情况
// 1、如果高度超过
if(aPlatform[L].h - aPlatform[j].h > max_h)
return INFINITE;
// 2、没超过,就计算左边的时间和右边的时间,取两者中最短的
int hTime=aPlatform[L].h - aPlatform[j].h;//下落时间
int leftTime=x-aPlatform[j].Lx;//向左走的时间
int rightTime=aPlatform[j].Rx-x;//向右走的时间
if(aLeftMinTime[j]==-1)
aLeftMinTime[j]=MinTime(j, true);
if(aRightMinTime[j]==-1)
aRightMinTime[j]=MinTime(j, false);
if(leftTime+aLeftMinTime[j]<rightTime+aRightMinTime[j])
return hTime+leftTime+aLeftMinTime[j];//下落+向左+下层向左掉落
else
return hTime+rightTime+aRightMinTime[j];
}
int main()
{
scanf("%d", &t);
for( int i = 0;i < t; i ++ ) {
memset(aLeftMinTime, -1, sizeof(aLeftMinTime));
memset(aRightMinTime, -1, sizeof(aRightMinTime));
scanf("%d%d%d%d", &n, &x, &y, &max_h);
aPlatform[0].Lx=aPlatform[0].Rx=x;
aPlatform[0].h =y;
for(int j=1;j<=n;j++)
scanf("%d%d%d", & aPlatform[j].Lx, & aPlatform[j].Rx, & aPlatform[j].h);
sort(aPlatform, aPlatform+n+1);
// qsort(aPlatform, n+1, sizeof(Platform), MyCompare);
// for(int i=0;i<=n;i++)
// {
// printf("%d %d %d ", aPlatform[i].Lx, aPlatform[i].Rx, aPlatform[i].h);
// }
printf("%d
", MinTime(0, true));
}
return 0;
}
递推方式
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
#define MAX_N 1000
#define INFINITE 1000000
int t, n, x, y, MAX;
struct Platform{
int Lx, Rx, h;
//根据h从小到大排列
bool operator <(const Platform& r) const
{
return h<r.h;
}
} ;
Platform aPlatform[MAX_N + 10];
int aLeftMinTime[MAX_N + 10];
int aRightMinTime[MAX_N + 10];
int main()
{
scanf("%d", &t);
for( int i = 0;i < t; i ++ ) {
memset(aLeftMinTime, 0x3f, sizeof(aLeftMinTime));
memset(aRightMinTime, 0x3f, sizeof(aRightMinTime));
scanf("%d%d%d%d", &n, &x, &y, &MAX);
aPlatform[n].Lx = x;
aPlatform[n].Rx = x;
aPlatform[n].h = y;
for( int j = 0; j < n; j ++ )
scanf("%d%d%d", & aPlatform[j].Lx, & aPlatform[j].Rx, & aPlatform[j].h);
//qsort(aPlatform, n+1, sizeof(Platform), MyCompare);
sort(aPlatform, aPlatform+n);
// 最下面的平台开始,从下往上倒推
for(int j=0;j<=n;j++)
{
//分别找左边和右边掉落,碰到的平台编号
int lp=-1, rp=-1;
for(int k=j-1;k>=0;k--)
{
if(lp==-1 && aPlatform[k].Lx<=aPlatform[j].Lx && aPlatform[k].Rx>=aPlatform[j].Lx)
{
lp=k;
}
if(rp==-1 && aPlatform[k].Lx<=aPlatform[j].Rx && aPlatform[k].Rx>=aPlatform[j].Rx)
{
rp=k;
}
}
if(lp==-1 && aPlatform[j].h<=MAX)
aLeftMinTime[j]=aPlatform[j].h;
if(rp==-1 && aPlatform[j].h<=MAX)
aRightMinTime[j]=aPlatform[j].h;
if(lp!=-1 && (aPlatform[j].h-aPlatform[lp].h)<=MAX)
{
aLeftMinTime[j]=aPlatform[j].h-aPlatform[lp].h
+ min(aPlatform[j].Lx-aPlatform[lp].Lx+aLeftMinTime[lp],aPlatform[lp].Rx-aPlatform[j].Lx+aRightMinTime[lp]);
}
if(rp!=-1 && (aPlatform[j].h-aPlatform[rp].h)<=MAX)
{
aRightMinTime[j]=aPlatform[j].h-aPlatform[rp].h
+ min(aPlatform[j].Rx-aPlatform[rp].Lx+aLeftMinTime[rp],aPlatform[rp].Rx-aPlatform[j].Rx+aRightMinTime[rp]);
}
}
printf("%d ", aLeftMinTime[n]);
// printf("%d ", aRightMinTime[n]);
}
}
/*
1
4 14 5 6
3 22 1
16 23 2
16 30 3
13 21 4
答案:15
*/