POJ 1661动态规划解法
题目见如下截图所示:
直接贴上代码:
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
/*
**整个问题分解为两个子问题,即Jimmy所在位置下方第一块左端为起点到地面的最短时间,
**和右端为起点到地面的最短时间。不妨认为其开始位置是一个编号为0,长度为0的板子,
**LeftMinTime(k)表示从k板子左端到地面的最短时间,RightMinTime(k)表示从k号板子右端到
**地面的最短时间
*/
#define NOTAVALIBLE -2
typedef struct pingtai
{
int lx;
int rx;
int h;
}pingtai, *ppingtai;
ppingtai INFO;
int LEFTMINTIME[1010];
int RIGHTMINTIME[1010];
int MAX, N;
int LeftMinTime(int);
int RightMinTime(int);
//按照高度从高到低以及横坐标从低到高进行结构体的排序
bool cmp(pingtai a, pingtai b)
{
if(a.h != b.h)
return a.h > b.h;
else
return a.lx < b.lx;
}
int main(void)
{
int t;
cin >> t;
int X, Y;
while(t--)
{
//依次读入平台的数目以及起始位置
cin >> N >> X >> Y >> MAX;
INFO = (ppingtai)malloc((N + 1) * sizeof(pingtai));
for(int i = 1; i < N + 1; ++i){
cin >> INFO[i].lx >> INFO[i].rx >> INFO[i].h;
LEFTMINTIME[i] = -1;
RIGHTMINTIME[i] = -1;
}
INFO[0].lx = X;
INFO[0].rx = X;
INFO[0].h = Y;
LEFTMINTIME[0] = -1;
RIGHTMINTIME[0] = -1;
sort(INFO, INFO + N + 1, cmp);
cout << LeftMinTime(0) << endl;
}
return 0;
}
//参数k表示编号为k的平板的最左端到地面的最短时间
int LeftMinTime(int k)
{
if(LEFTMINTIME[k] != -1)
return LEFTMINTIME[k];
int i, flag = 0;
for(i = k + 1; i < N + 1; ++i)
{
if(INFO[k].lx >= INFO[i].lx && INFO[k].lx <= INFO[i].rx){
flag = 1;
break;
}
}
if(flag == 0) //表示下方无平台
{
if(INFO[k].h > MAX)
{
LEFTMINTIME[k] = NOTAVALIBLE;
return NOTAVALIBLE;
}
else{
LEFTMINTIME[k] = INFO[k].h;
return INFO[k].h;
}
}
else
{
int height = INFO[k].h - INFO[i].h;
if(height > MAX){
LEFTMINTIME[k] = NOTAVALIBLE;
return NOTAVALIBLE;
}
int lret, rret;
lret = LeftMinTime(i);
rret = RightMinTime(i);
if(lret == NOTAVALIBLE && rret == NOTAVALIBLE){
LEFTMINTIME[k] = NOTAVALIBLE;
}
else if(lret != NOTAVALIBLE && rret != NOTAVALIBLE){
LEFTMINTIME[k] = min(INFO[k].lx - INFO[i].lx + LeftMinTime(i), INFO[i].rx - INFO[k].lx + RightMinTime(i)) + height;
}
else if(lret != NOTAVALIBLE){
LEFTMINTIME[k] = height + INFO[k].lx - INFO[i].lx + LeftMinTime(i);
}
else{
LEFTMINTIME[k] = height + INFO[i].rx - INFO[k].lx + RightMinTime(i);
}
return LEFTMINTIME[k];
}
}
int RightMinTime(int k)
{
if(RIGHTMINTIME[k] != -1)
return RIGHTMINTIME[k];
int i, flag = 0;
for(i = k + 1; i < N + 1; ++i)
{
if(INFO[k].rx >= INFO[i].lx && INFO[k].rx <= INFO[i].rx){
flag = 1;
break;
}
}
if(flag == 0) //表示下方无平台
{
if(INFO[k].h > MAX)
{
RIGHTMINTIME[k] = NOTAVALIBLE;
return NOTAVALIBLE;
}
else{
RIGHTMINTIME[k] = INFO[k].h;
return INFO[k].h;
}
}
else
{
int height = INFO[k].h - INFO[i].h;
if(height > MAX){
RIGHTMINTIME[k] = NOTAVALIBLE;
return NOTAVALIBLE;
}
int lret, rret;
lret = LeftMinTime(i);
rret = RightMinTime(i);
if(lret == NOTAVALIBLE && rret == NOTAVALIBLE){
RIGHTMINTIME[k] = NOTAVALIBLE;
}
else if(lret != NOTAVALIBLE && rret != NOTAVALIBLE){
RIGHTMINTIME[k] = min(INFO[k].rx - INFO[i].lx + LeftMinTime(i), INFO[i].rx - INFO[k].rx + RightMinTime(i)) + height;
}
else if(lret != NOTAVALIBLE){
RIGHTMINTIME[k] = height + INFO[k].rx - INFO[i].lx + LeftMinTime(i);
}
else{
RIGHTMINTIME[k] = height + INFO[i].rx - INFO[k].rx + RightMinTime(i);
}
return RIGHTMINTIME[k];
}
}