动态规划3--Help Jimmy

一、心得

二、题目

三、分析

Jimmy跳到一块板上后,可以有两种选择,向左走,或向右走。
走到左端和走到右端所需的时间,是很容易算的。
如果我们能知道,以左端为起点到达地面的最短时间,和以右端为起点到达地面的最短时间,那么向左走还是向右走,就很容选择了。
因此,整个问题就被分解成两个子问题,即Jimmy所在位置下方第一块板左端为起点到地面的最短时间,和右端为起点到地面的最短时间。
这两个子问题在形式上和原问题是完全一致的。将板子从上到下从1开始进行无重复的编号(越高的板子编号越小,高度相同的几块板子,哪块编号在前无所谓),那么,和上面两个子问题相关的变量就只有板子的编号。

将板子由高到低按从0到n编号,起始点的为0
不妨认为Jimmy开始的位置是一个编号为0,长度为0的板子
设LeftMinTime(k)表示从k号板子左端到地面的最短时间
RightMinTime(k)表示从k号板子右端到地面的最短时间

 if ( 板子k左端正下方没有别的板子) {
if( 板子k的高度 h(k) 大于Max)
LeftMinTime(k) = ∞;
else
LeftMinTime(k) = h(k);
}
else if( 板子k左端正下方的板子编号是m )
LeftMinTime(k) = h(k)-h(m) +
Min( LeftMinTime(m) + Lx(k)-Lx(m),
RightMinTime(m) + Rx(m)-Lx(k));
}

上面,h(i)就代表i号板子的高度,Lx(i)就代表i号板子左端点的横坐标,Rx(i)就代表i号板子右端点的横坐标。那么 h(k)-h(m) 当然就是从k号板子跳到m号板子所需要的时间,Lx(k)-Lx(m) 就是从m号板子的落脚点走到m号板子左端点的时间,Rx(m)-Lx(k)就是从m号板子的落脚点走到右端点所需的时间。
求RightMinTime(k)的过程类似。
不妨认为Jimmy开始的位置是一个编号为0,长度为0的板子,那么整个问题就是要求LeftMinTime(0)。
输入数据中,板子并没有按高度排序,所以程序中一定要首先将板子排序。

时间复杂度: 一共 n个板子,每个左右两端的最小时间各算一次 O(n) 找出板子一段到地面之间有那块板子,需要遍历板子 O(n) 总的时间复杂度O(n2)

四、代码及结果

1、记忆化递归

 /*
POJ1661 Help Himmy
这样效率太低了,一早上没看几个题
代码要是不是特别好看懂,先把伪代码写出来就比较好懂了 分析:
将板子由高到低按从0到n编号,起始点的为0
不妨认为Jimmy开始的位置是一个编号为0,长度为0的板子
设LeftMinTime(k)表示从k号板子左端到地面的最短时间
RightMinTime(k)表示从k号板子右端到地面的最短时间
if ( 板子k左端正下方没有别的板子) {
if( 板子k的高度 h(k) 大于Max)
LeftMinTime(k) = ∞;
else
LeftMinTime(k) = h(k);
}
else if( 板子k左端正下方的板子编号是m )
LeftMinTime(k) = h(k)-h(m) +
Min( LeftMinTime(m) + Lx(k)-Lx(m),
RightMinTime(m) + Rx(m)-Lx(k));
}
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
#define MAX_N 1000
#define INFINITE 1000000
int t,n,x,y,maxHeight;
struct Platform{//定义平台结构体
int Lx, Rx, h;//Lx表示做边界横坐标,Rx表示右边界横坐标,h表示高度
bool operator < (const Platform & p2) const {//符号重载,sort的时候能按h从高到低排
return h > p2.h;
}
};
Platform platForms[MAX_N + ];//平台
int leftMinTime[MAX_N + ];//走左边的最小时间
int rightMinTime[MAX_N + ];//走右边的最小时间
int L[MAX_N + ];//
//l表示现在这块板的编号,越在上面的编号越小,bleft表示是否向左边走
//因为这题分为向左和向右两种情况
int MinTime( int l, bool bLeft )//l表示现在这块板的编号,越在上面的编号越小,bleft表示是否向左边走
{
//初始化x和y坐标,如果是去左边,就走到左边边上,如果去右边,就走到右边边上
int y = platForms[l].h;
int x;
//如果是去左边,就走到左边边上,如果去右边,就走到右边边上
if(bLeft)
x = platForms[l].Lx;
else
x = platForms[l].Rx;
int i;
for( i = l + ;i <= n;i ++ ) {//找到现在这块板下面的那块板
if( platForms[i].Lx <= x && platForms[i].Rx >= x)//判断从当前条能跳到的小一块板子上
break;
}
if( i <= n ) {// 板子k左端正下方有别的板
if( y - platForms[i].h > maxHeight )// 跳到这块平台的高度如果大于Max
return INFINITE;//返回无限大
}
else {// 板子k左端正下方没有别的板
if( y > maxHeight )//板子k的高度 h(k) 大于Max
return INFINITE;//返回无限大
else
return y;//如果可以直接跳下,就输出y
}
int nLeftTime = y - platForms[i].h + x - platForms[i].Lx;//现在平台与下一块平台的高度差以及下一块平台左边界的距离
int nRightTime = y - platForms[i].h + platForms[i].Rx - x;//现在平台与下一块平台的高度差以及下一块平台右边界的距离
if( leftMinTime[i] == - ) //等于-1表示我初始化过 ,如果还可以向左我们就向左
leftMinTime[i] = MinTime(i,true);//向左进入子问题
if( L[i] == - )//等于-1表示我初始化过 ,如果还可以向右我们就向右
L[i] = MinTime(i,false);//像右进入子问题
nLeftTime += leftMinTime[i];//左边固定花费的时间加上下一场左边这样的时间
nRightTime += L[i];//右边固定花费的时间加上下一场右边这样的时间
//返回左边和右边走中值小的那一个
if( nLeftTime < nRightTime )
return nLeftTime;
return nRightTime;
} int main() {
freopen("in.txt","r",stdin);
scanf("%d",&t);//读入t组数据
for( int i = ;i < t; i ++ ) {//对每组数据进行操作
memset(leftMinTime,-,sizeof(leftMinTime));//初始化leftMinTime
memset(L,-,sizeof(rightMinTime));//初始化L
scanf("%d%d%d%d",&n, &x, &y, &maxHeight);//读入数据
platForms[].Lx = x; platForms[].Rx = x;
platForms[].h = y;//起始点初始化
for( int j = ; j <= n; j ++ )//读入平台信息
scanf("%d%d%d",&platForms[j].Lx,& platForms[j].Rx, & platForms[j].h);
sort(platForms,platForms+n+);//对平台由高到低排序
printf("%d\n", MinTime(,true));//MinTime()方法求下平台的最小时间
}
return ;
}

动态规划3--Help Jimmy的更多相关文章

  1. OpenJudge/Poj 1661 帮助 Jimmy

    1.链接地址: bailian.openjudge.cn/practice/1661 http://poj.org/problem?id=1661 2.题目: 总Time Limit: 1000ms ...

  2. 【POJ - 1661】Help Jimmy (动态规划)

    Help Jimmy Descriptions: "Help Jimmy" 是在下图所示的场景上完成的游戏. 场景中包括多个长度和高度各不相同的平台.地面是最低的平台,高度为零,长 ...

  3. POJ 1661 Help Jimmy(C)动态规划

    没刷过 POJ,这题是论坛有人问的,我才看看. 我发现 POJ 注册很奇怪,账号总是登不上去,弄的我还注册两个.Emmm 首次体验很差,还好我不在 POJ 刷题. 题目链接:POJ 1661 Help ...

  4. 递归,动态规划,找最短路径,Help Jimmy

    题目链接:http://poj.org/problem?id=1661 解题报告: 1.老鼠每次来到一块木板上都只有两条路可以走,可以使用递归 #include <stdio.h> #in ...

  5. POJ 1661 Help Jimmy -- 动态规划

    题目地址:http://poj.org/problem?id=1661 Description "Help Jimmy" 是在下图所示的场景上完成的游戏. 场景中包括多个长度和高度 ...

  6. Help Jimmy(动态规划)

    点击打开链接 Help Jimmy Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 12168   Accepted: 402 ...

  7. 【动态规划】POJ1661 Help Jimmy

    Help Jimmy Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 11621   Accepted: 3827 Descr ...

  8. POJ 1661 Help Jimmy (dijkstra,最短路)

    刚在百度搜索了一下这道题的题解, 因为看到有别人用动态规划做的,所以想参考一下. 结果顺带发现了有那么几个网站,上面的文章竟然和我这篇一模一样(除了一些明显的错别字外),我去,作者还是同一个人Admi ...

  9. poj 动态规划题目列表及总结

    此文转载别人,希望自己能够做完这些题目! 1.POJ动态规划题目列表 容易:1018, 1050, 1083, 1088, 1125, 1143, 1157, 1163, 1178, 1179, 11 ...

随机推荐

  1. 2:5 视图控制器result的配置

    result:   1:其实底层还是使用原来servlet的转发和重定向的方法: 2:redirectAction:只能定位到 action (比如下面name属性为 *User 的Action ,但 ...

  2. Rpgmakermv(5) MiniLabel插件介绍

    ============================================================================ Introduction ========== ...

  3. fontawesome与amazeUI

    fontawesome是很不错的东西呢~~~~ amazeUI也是很不错的东西呢~~~~~ 最近一年里,比较偏爱这两个家伙? 什么?为什么bootstrap?有什么区别? 这个我还真说不太清楚. 用一 ...

  4. VS2010/MFC编程入门之五十一(图形图像:GDI对象之画刷CBrush)

    上一节中鸡啄米主要讲的是画笔CPen的用法,前面也说了,GDI对象中最常用的就是画笔和画刷,本节就讲讲画刷CBrush. 鸡啄米依然是通过实例的方式来说明画刷的用法.此实例要实现的功能是,对话框上有一 ...

  5. python print 使用分隔符 或行尾符

    使用print() 函数输出数据,但是想改变默认的分隔符或者行尾符. >>> print('ACME', 50, 91.5) ACME 50 91.5 >>> pr ...

  6. QImage与QPixmap完全解析

    转载自http://www.civilnet.cn/bbs/browse.php?topicno=4691 用Qt程序在手机上显示一幅图片对编程人员来说是再基础不过的一件事情了.那么先让大家看两段代码 ...

  7. keepalived+MySQL高可用集群

    基于keepalived搭建MySQL的高可用集群   MySQL的高可用方案一般有如下几种: keepalived+双主,MHA,MMM,Heartbeat+DRBD,PXC,Galera Clus ...

  8. ES6学习--函数剩余参数 (rest参数)

    ES6 引入 rest 参数(形式为“...变量名”),用于获取函数的多余参数,这样就不需要使用arguments对象了.rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中.(可以拿到除 ...

  9. Linux解压文件到指定目录

    Linux解压文件到指定目录 tar在Linux上是常用的打包.压缩.加压缩工具,他的参数很多,折里仅仅列举常用的压缩与解压缩参数 参数:-c :create 建立压缩档案的参数:-x : 解压缩压缩 ...

  10. 使用dll,将image库开放出去

    这是很经典的想法了,但是如何来做,不经过摸索不知道细节.   最简单: dll处   #include "stdafx.h"   #ifdef _DEBUG #define new ...