题意
Jimmy老鼠在时刻0从高于所有平台的某处开始下落,它的下落速度始终为1米/秒。当Jimmy落到某个平台上时,游戏者选择让它向左还是向右跑,它跑动的速度也是1米/秒。当Jimmy跑到平台的边缘时,开始继续下落。Jimmy***每次下落的高度不能超过MAX米*,不然就会摔死,游戏也会结束
思路
自己的思路本来是每个板子存两个时间,然后分别对两个端点dp
写出来的话差不多就这个样http://blog.csdn.net/yukizzz/article/details/51063447###;然后看了dalao的博客
直接一个点开左右两维,同时找到左右下方的点,同时对左右做dp
666
dp[i][0] = min(dp[k][0]+l[i]-l[k], dp[k][1]+r[i]-l[k]) + h[i]-h[k]; (左左和左右取最小)
dp[i][1] = min(dp[k][0]+r[i]-l[k], dp[k][1]+r[i]-r[k]) + h[i]-h[k];(右左和右右取最小)
要注意对下方直接为地面的台层的特殊处理,以及应当注意的细节题目都已说明,已在上面标记。
代码
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <queue>
#include <stack>
#define N 1005
#define INF 0x7f7f7f7f
using namespace std;
struct Node {
int l, r, h;
//按高度排序
bool operator< ( const Node &t ) const { return h < t.h; }
} node[ N ];
int dp[ N ][ 2 ];
int main () {
int T;
cin >> T;
while ( T-- ) {
int n, x, y, mx;
cin >> n >> x >> y >> mx;
memset ( dp, INF, sizeof ( dp ) );
// INpt
for ( int i = 0; i < n; ++i )
cin >> node[ i ].l >> node[ i ].r >> node[ i ].h;
node[ n ].l = x, node[ n ].r = x, node[ n ].h = y;
//按从小到大高度排序
sort ( node, node + n );
for ( int i = 0; i <= n; ++i ) {
//找到左右两个端点下方合适的板子
int lp, rp;
lp = rp = -1;
for ( int k = i - 1; k >= 0; --k ) {
if ( lp == -1 && node[ k ].l <= node[ i ].l && node[ k ].r >= node[ i ].l )
lp = k;
if ( rp == -1 && node[ k ].l <= node[ i ].r && node[ k ].r >= node[ i ].r )
rp = k;
}
//下面没有板子且高度<max
if ( lp == -1 && node[ i ].h <= mx )
dp[ i ][ 0 ] = node[ i ].h;
if ( rp == -1 && node[ i ].h <= mx )
dp[ i ][ 1 ] = node[ i ].h;
//左端点
if ( lp != -1 && node[ i ].h - node[ lp ].h <= mx )
dp[ i ][ 0 ] = min ( dp[ lp ][ 0 ] + node[ i ].l - node[ lp ].l,
dp[ lp ][ 1 ] + node[ lp ].r - node[ i ].l ) +
node[ i ].h - node[ lp ].h;
if ( rp != -1 && node[ i ].h - node[ rp ].h <= mx )
dp[ i ][ 1 ] = min ( dp[ rp ][ 0 ] + node[ i ].r - node[ rp ].l,
dp[ rp ][ 1 ] + node[ rp ].r - node[ i ].r ) +
node[ i ].h - node[ rp ].h;
}
printf ( "%d\n", dp[ n ][ 1 ] );
}
return 0;
}