http://poj.org/problem?id=1661
找到下落的最短时间
大概就是已知下面的算上面的?自底向上的步骤然后找出左右当中较小的就完成了DP优化?( ̄▽ ̄)
果然还是不太懂DP的套路hhh
和网上的代码一模一样系列
#include <algorithm>
#include <cstdio>
#include <iostream>
#define INF 999999999;
int N, X, Y, MAX;
int T[ 1010 ][ 2 ];
struct Plate {
int x1, x2, h; //左坐标,右坐标,高度
} p[ 1010 ];
bool cmp ( const Plate &a, const Plate &b ) { return a.h < b.h; } //按照高度排序的比较函数
int min ( int a, int b ) { return a < b ? a : b; }
void left ( int i ) { //从板子i的左侧下落的最短时间
int k = i - 1;
while ( k > 0 && p[ i ].h - p[ k ].h <= MAX ) { //找到比自己矮的,且两者之间距离不超过MAX
if ( p[ i ].x1 >= p[ k ].x1 &&
p[ i ].x1 <= p[ k ].x2 ) { //板子i的x1(左侧)处于板子k的x1,x2之间
T[ i ][ 0 ] =
( p[ i ].h - p[ k ].h ) +
min ( ( T[ k ][ 0 ] + p[ i ].x1 - p[ k ].x1 ),
( T[ k ][ 1 ] + p[ k ].x2 - p[ i ].x1 ) ); //计算较短的时间
return;
}
k--;
}
if ( p[ i ].h > MAX ) { //如果左侧下方已经没有其他板子(不满足上方的if)
T[ i ][ 0 ] = INF; //高度超过MAX则无解
} else
T[ i ][ 0 ] = p[ i ].h; //未超过则直接落地
}
void right ( int i ) { //从板子i的右侧下落的最短时间
int k = i - 1;
while ( k > 0 && p[ i ].h - p[ k ].h <= MAX ) {
if ( p[ i ].x2 >= p[ k ].x1 &&
p[ i ].x2 <= p[ k ].x2 ) { //板子i的x2(右侧)处于板子k的x1,x2之间
T[ i ][ 1 ] = ( p[ i ].h - p[ k ].h ) +
min ( ( T[ k ][ 0 ] + p[ i ].x2 - p[ k ].x1 ),
( T[ k ][ 1 ] + p[ k ].x2 - p[ i ].x2 ) );
return;
}
k--;
}
if ( p[ i ].h > MAX ) {
T[ i ][ 1 ] = INF;
} else
T[ i ][ 1 ] = p[ i ].h;
}
int Time () {
for ( int i = 1; i <= N + 1; i++ ) { //从最低的板子开始向上计算
right ( i );
left ( i );
}
return min ( T[ N + 1 ][ 0 ], T[ N + 1 ][ 1 ] ); //返回左右侧较短的时间值
}
int main () {
int t;
scanf ( "%d", &t );
while ( t-- ) {
scanf ( "%d%d%d%d", &N, &X, &Y, &MAX );
for ( int i = 1; i <= N; i++ )
scanf ( "%d%d%d", &p[ i ].x1, &p[ i ].x2, &p[ i ].h );
// p[0]代表地面
p[ 0 ].h = 0;
p[ 0 ].x1 = -20000;
p[ 0 ].x2 = 20000;
// p[ N+1 ]代表jimmy所在的位置
p[ N + 1 ].h = Y;
p[ N + 1 ].x1 = X;
p[ N + 1 ].x2 = X; //左右坐标都设置为当前的X位置
std::sort ( p, p + N + 2, cmp );
printf ( "%d\n", Time () );
}
return 0;
}