题意:
Jimmy从最高点(x, y)跳到地面,但高度不能超过MAX,否则jimmy会跳死,所以jimmy可能要借助给出的n与地面平行的平面,平面的高度为h,水平范围从x1到x2。jimmy在水平和竖直方向的运动速度都是1m/s。求jimmy跳到地面的最小时间。
思路:
把最高点(x, y)视为一个(x1, x2, h) = (x, x, y)的平面,按高度从低到高给这n + 1个平面排序,dp[i][0]表示从下面平跳到i平面左端点的最少花费时间,dp[i][1]表示从下面平跳到i平面右端点的最少花费时间,枚举每个dp[i][0],dp[i][1]就是了。dp转移式为:
dp[i][0] = min(dp[i][0], dp[j][0] + (op[i].h - op[j].h) + (op[i].x1 - op[j].x1));
dp[i][0] = min(dp[i][0], dp[j][1] + (op[i].h - op[j].h) + (op[j].x2 - op[i].x1));
dp[i][1] = min(dp[i][1], dp[j][0] + (op[i].h - op[j].h) + (op[i].x2 - op[j].x1));
dp[i][1] = min(dp[i][1], dp[j][0] + (op[i].h - op[j].h) + (op[j].x2 - op[i].x2));
(0 <= j < i <= n)
注意Jimmy的最大跳跃高度为MAX,且平面只能从两端往下跳,不能穿过一个平面跳到另一个平面。
code:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 1e3 + 5;
const int inf = 1e9 + 5;
struct node{
int x1, x2, h;
bool operator < (const node& p) const {
return h < p.h;
}
} op[maxn];
int dp[maxn][2];
void init(int n){
for(int i = 0; i <= n; i++)
for(int j = 0; j < 2; j++)
dp[i][j] = inf;
}
int main(){
int T, n, x, y, MAX;
scanf("%d", &T);
while(T--){
scanf("%d%d%d%d", &n, &x, &y, &MAX);
init(n);
for(int i = 1; i <= n; i++)
scanf("%d%d%d", &op[i].x1, &op[i].x2, &op[i].h);
op[0].x1 = x;
op[0].x2 = x;
op[0].h = y;
sort(op, op + n + 1); //按高度排序
for(int i = 0; i <= n; i++) {
bool flag1 = true, flag2 = true;
for(int j = i - 1; j >= 0; j--){ // j从i - 1开始是为了防止穿过某一平面跳到更下面的平面
int gaph = op[i].h - op[j].h;
int upx1 = op[i].x1, upx2 = op[i].x2;
int downx1 = op[j].x1, downx2 = op[j].x2;
if(gaph <= MAX) { //状态转移
if(upx1 >= downx1 && upx1 <= downx2 && flag1) { //flag1用来标记是否有平面阻隔再i,j平面间
dp[i][0] = min(dp[i][0], gaph + dp[j][0] + upx1 - downx1);
dp[i][0] = min(dp[i][0], gaph + dp[j][1] + downx2 - upx1);
flag1 = false;
}
if(upx2 >= downx1 && upx2 <= downx2 && flag2) {
dp[i][1] = min(dp[i][1], gaph + dp[j][0] + upx2 - downx1);
dp[i][1] = min(dp[i][1], gaph + dp[j][1] + downx2 - upx2);
flag2 = false;
}
}
}
if(flag1 && op[i].h <= MAX) dp[i][0] = min(dp[i][0], op[i].h);
if(flag2 && op[i].h <= MAX) dp[i][1] = min(dp[i][1], op[i].h);
}
printf("%d\n", dp[n][0]);
}
}