帮助 Jimmy
help jimmy 问题描述以及在线测试平台:http://bailian.openjudge.cn/practice/1661/
思路:
作者通过郭炜老师在大学慕课的程序设计与算法(二)中了解到这道题,并且课程中提到了这道题的结题思路,所以没有思路的小伙伴建议先看下郭炜老师的视频在再来看下面的源程序。
源码
#include<iostream>
#include<algorithm>
#define MAXX 99999999
using namespace std;
const int MAX = 1005;
int n,maxx;
int xj,yj;
int m;
struct pin {
int x1,x2;
int h;
} a[MAX];
int dp[MAX][2]; //0表示第i的木板左边到底最短的时间 1表示右边的时间
int cmp(pin x, pin y) {
return x.h < y.h;
}
void LeftMinTime(int i) {
int k;
for(k = i-1; k > 0 && a[i].h - a[k].h <= maxx; k--) {//如果有板子,并且高度差在允许范围内,则必须跳到这个板子上
if( a[k].x1 <= a[i].x1 && a[i].x1 <= a[k].x2 ) { //k板必须要在i板的下方特定范围内,不然无法下调落到k板
dp[i][0] = a[i].h - a[k].h + min(dp[k][0] + a[i].x1- a[k].x1, dp[k][1] +a[k].x2 - a[i].x1) ;
return ;
}
}
//这块板子下面没有板子了,就只能调到地上
if(a[i].h - a[k].h > maxx) //距离过大,无法下落给个最大的数
dp[i][0] = MAXX;
else
dp[i][0] = a[i].h - a[k].h;
}
void RightMinTime(int i) {
int k;
for( k = i-1; k > 0 && a[i].h - a[k].h <= maxx; k--) { //如果有板子,并且高度差在允许范围内,则必须跳到这个板子上
if( a[k].x1 <= a[i].x2 && a[i].x2 <= a[k].x2 ) { //k板必须要在i板的下方特定范围内,不然无法下调落到k板
dp[i][1] = a[i].h - a[k].h + min(dp[k][0] + a[i].x2- a[k].x1, dp[k][1] +a[k].x2 - a[i].x2) ;
return;
}
}
//这块板子下面没有板子了,就只能调到地上
if(a[i].h - a[k].h > maxx) //距离过大,无法下落给个最大的数
dp[i][1] = MAXX;
else
dp[i][1] = a[i].h - a[k].h;
}
int main() {
int t;
cin>>t;
while(t--) {
int flag = 0;
cin>>n;
cin>>xj>>yj>>maxx; //读入并初始化jimmy位置信息的数据,以及最大能下落的高度
a[0].x1 = -20000; //初始化地板的位置
a[0].x2 = 20000;
a[0].h = 0;
m = n;
for(int i=1; i<=m; i++) {
cin>>a[i].x1>>a[i].x2>>a[i].h;
if(a[i].x1 > a[i].x2) //如果x1 大于 x2 则需要交换他们之间的位置
swap(a[i].x1, a[i].x2);
//如果平台出现在jimmy的上方则需要剔除平台
if(a[i].h > yj ) {
n--;
i--;
m--;
}
}
//以jimmy的位置作为最高的台阶
a[n+1].x1 = a[n+1].x2 = xj;
a[n+1].h = yj;
sort(a+1,a+n+1,cmp);//初始化中板子没有排序,一定要首先将板子排序,这里是按照从低到高排序
for(int i=1; i<=n+1; i++) { //没循环一次都可以往 dp数组中存入两个值
LeftMinTime(i);
RightMinTime(i);
}
cout<<min(dp[n+1][0], dp[n+1][1])<<endl;
}
return 0;
}
附上:
郭炜老师讲解思路:视频链接
测试数据参考:链接
源码参考:代码也存在一些问题,带上以及被被本作者修改,尽量参考本作者代码
重点关注测试用例
1
2 2 3 5
1 4 4
0 2 2
答案为 3