题干:

Help Jimmy" 是在下图所示的场景上完成的游戏。

场景中包括多个长度和高度各不相同的平台。地面是最低的平台,高度为零,长度无限。

Jimmy老鼠在时刻0从高于所有平台的某处开始下落,它的下落速度始终为1米/秒。当Jimmy落到某个平台上时,游戏者选择让它向左还是向右跑,它跑动的速度也是1米/秒。当Jimmy跑到平台的边缘时,开始继续下落。Jimmy每次下落的高度不能超过MAX米,不然就会摔死,游戏也会结束。

设计一个程序,计算Jimmy到底地面时可能的最早时间。

Input

第一行是测试数据的组数t(0 <= t <= 20)。每组测试数据的第一行是四个整数N,X,Y,MAX,用空格分隔。N是平台的数目(不包括地面),X和Y是Jimmy开始下落的位置的横竖坐标,MAX是一次下落的最大高度。接下来的N行每行描述一个平台,包括三个整数,X1[i],X2[i]和H[i]。H[i]表示平台的高度,X1[i]和X2[i]表示平台左右端点的横坐标。1 <= N <= 1000,-20000 <= X, X1[i], X2[i] <= 20000,0 < H[i] < Y <= 20000(i = 1..N)。所有坐标的单位都是米。

Jimmy的大小和平台的厚度均忽略不计。如果Jimmy恰好落在某个平台的边缘,被视为落在平台上。所有的平台均不重叠或相连。测试数据保证问题一定有解。

Output

对输入的每组测试数据,输出一个整数,Jimmy到底地面时可能的最早时间。

AC代码1:

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
using namespace std;
const int INF = 0x3f3f3f3f;
int n,x,y,maxx;
int dp[1005][2];//fg=0代表左边,fg=1代表右边
struct Node {int l,r,h;
} node[1005];
bool cmp(const Node & a,const Node & b) {return a.h < b.h;
}
int dfs(int cur,int fg) {if(cur == 1) return 0;if(dp[cur][fg] != -1) return dp[cur][fg];if(cur == 1) {return 0;}int ans = INF;if(dp[cur][fg] != -1) {return dp[cur][fg];}int temp = cur;    for(int i = cur-1; i>=1; i--) {temp=i;if(node[cur].h - node[i].h > maxx) break;if(fg==0) {if(node[i].l <= node[cur].l && node[i].r >= node[cur].l) {ans = min(dfs(i,0)+node[cur].l-node[i].l,dfs(i,1) +node[i].r-node[cur].l );break;}} else {if(node[i].r >= node[cur].r && node[i].l <= node[cur].r) {ans = min(dfs(i,0)+node[cur].r-node[i].l,dfs(i,1)+node[i].r-node[cur].r);break;}}}if(ans == INF) {if(node[cur].h <= maxx) return dp[cur][fg] = 0;else return dp[cur][fg] = ans;}else return dp[cur][fg] = ans;
}
int main()
{int t;cin>>t;while(t--) {scanf("%d%d%d%d",&n,&x,&y,&maxx);memset(dp,-1,sizeof (dp));for(int i = 1; i<=n; i++) {scanf("%d%d%d",&node[i].l,&node[i].r,&node[i].h);}sort(node+1,node+n+1,cmp);int ok=n+1;
//      node[ok].h = y;node[ok].l=node[ok].r=x;for(int i = n; i>=1; i--) {if(node[i].r >= x && node[i].l <= x) {ok=i;break;}}if(ok == n+1) {printf("%d\n",y);}else {int ans = min(dfs(ok,1) + node[ok].r-x,dfs(ok,0) + x-node[ok].l) + y;
//          int ans = min(dfs(ok,1),dfs(ok,0)) + y;printf("%d\n",ans);}}    return 0 ;}
//1
//1
//2 3
//100
//5 6 1

AC代码2:

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
using namespace std;
const int INF = 0x3f3f3f3f;
int n,x,y,maxx;
int dp[1005][2];//fg=0代表左边,fg=1代表右边
struct Node {int l,r,h;
} node[1005];
bool cmp(const Node & a,const Node & b) {return a.h < b.h;
}
int dfs(int cur,int fg) {if(cur == 1) return 0;if(dp[cur][fg] != -1) return dp[cur][fg];
//  int minn = 0x3f3f3f3f,flag=0;//0左  1右
//  int temp=cur;int ans = INF;int temp = cur;   for(int i = cur-1; i>=1; i--) {temp=i;if(node[cur].h - node[i].h > maxx) break;if(fg==0) {if(node[i].l <= node[cur].l && node[i].r >= node[cur].l) {ans = min(dfs(i,0)+node[cur].l-node[i].l,dfs(i,1) +node[i].r-node[cur].l );break;}} else {if(node[i].r >= node[cur].r && node[i].l <= node[cur].r) {ans = min(dfs(i,0)+node[cur].r-node[i].l,dfs(i,1)+node[i].r-node[cur].r);break;}}}if(ans == INF) {if(node[cur].h <= maxx) return dp[cur][fg] = 0;else return dp[cur][fg] = ans;}else return dp[cur][fg] = ans;
//  if(ans == INF) {
//      if(temp == 1) {
//          if(node[cur].h > maxx) return dp[cur][fg] = ans;
//          else return dp[cur][fg] = 0;
//      }
//      return dp[cur][fg] = ans;
//  }
//  else return dp[cur][fg] = ans;
}
int main()
{int t;cin>>t;while(t--) {scanf("%d%d%d%d",&n,&x,&y,&maxx);memset(dp,-1,sizeof (dp));for(int i = 1; i<=n; i++) {scanf("%d%d%d",&node[i].l,&node[i].r,&node[i].h);}sort(node+1,node+n+1,cmp);int ok=n+1;node[ok].h = y;node[ok].l=node[ok].r=x;
//      for(int i = n; i>=1; i--) {
//          if(node[i].r >= x && node[i].l <= x) {
//              ok=i;break;
//          }
//      }
//      int ans = min(dfs(ok,1) + node[ok].r-x,dfs(ok,0) + x-node[ok].l) + y;int ans = min(dfs(ok,1),dfs(ok,0)) + y;printf("%d\n",ans);}    return 0 ;} 

错误代码:

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
using namespace std;
int n,x,y,maxx;
int dp[1005];
struct Node {int l,r,h;
} node[1005];
bool cmp(const Node & a,const Node & b) {return a.h < b.h;
}
int dfs(int cur,int curx,int curh) {if(curh == 0) return 0;if(cur < 0) return 0;if(dp[cur] != -1) return dp[cur];int minn = 0x3f3f3f3f;for(int i = cur-1; i>=1; i--) {if(curh - node[i].h > maxx) break;if(node[i].l <= node[cur].l) minn = min(minn,dfs(i,node[cur].l,node[i].h)+node[cur].l-curx);if(node[i].r >= node[cur].r) minn = min(minn,dfs(i,node[cur].r,node[i].h)+node[cur].r-curx);}return dp[cur] = minn;
}
int main()
{int t;cin>>t;while(t--) {scanf("%d%d%d%d",&n,&x,&y,&maxx);memset(dp,-1,sizeof (dp));for(int i = 1; i<=n; i++) {scanf("%d%d%d",&node[i].l,&node[i].r,&node[i].h);}sort(node+1,node+n+1,cmp);printf("%d\n",dfs(n,x,node[n].h));}
//  18653293769return 0 ;} 

总结:

几个地方是真的坑,首先这个错误代码,记忆化搜素的设计状态我就没搞明白(因为后来我通过观察发现一维dp表示不了所有状态),于是dfs中乱设了一堆参数,结果显然都没用。

其二,函数内部,显然要break,不能不加break,因为有上一个台子挡住了,后面即使有符合的,也不能跳上去了,所以要break。

其三,要处理好到地面的那一步,一定是直接跳过去的(也就是 一定ans==INF),所以return的时候不能直接retrun dp[cur][fg] = ans;而应该判断是否ans==INF 如果等于的话,也就说明是到地面了,要dp[cur][fg] = 0;才可以。

其四,有个处理技巧,让出发点当成一个新的平台,这样直接统一形式就可以了。不然的话,就跟AC代码1一样,先判断是否从出发点可以直接落到地面上,特判一下这个条件才可以。

其五,有个技巧,就是高度都最后统一算,直接+y就可以了,这样减少了代码出错概率。

其六,递归函数中的状态转移要想清楚,到底是由哪些状态转移而来,或者想,可以转移到哪些状态去。

【POJ - 1661】Help Jimmy(记忆化搜索,dp)相关推荐

  1. [蓝桥杯][算法提高VIP]夺宝奇兵(记忆化搜索||DP)

    题目描述 在一座山上,有很多很多珠宝,它们散落在山底通往山顶的每条道路上,不同道路上的珠宝的数目也各不相同.下图为一张藏宝地图: 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5 " ...

  2. 【牛客 - 301哈尔滨理工大学软件与微电子学院第八届程序设计竞赛同步赛(高年级)】小乐乐下象棋(记忆化搜索dp,dfs)

    题干: 小乐乐一天天就知道玩,这一天又想玩象棋. 我们都知道马走日. 现在给定一个棋盘,大小是n*m,把棋盘放在第一象限,棋盘的左下角是(0,0),右上角是(n - 1, m - 1); 小乐乐想知道 ...

  3. UVA10739 String to Palindrome【记忆化搜索+DP】

    In this problem you are asked to convert a string into a palindrome with minimum number of operation ...

  4. POJ 2111 Millenium Leapcow(记忆化搜索+dfs记录路径)

    题目链接 思路 对N*N网格中所有点进行搜索(dfs),搜索过程中对每一步进行记忆化存储,即dp数组保存从当前点开始可获得的最高得分,若后面需要用到前面计算过的数据,直接读取dp数组即可. dp[i] ...

  5. BZOJ2246 [SDOI2011]迷宫探险 【记忆化搜索dp + 概率】

    题目 输入格式 输出格式 仅包含一个数字,表示在执行最优策略时,人物活着走出迷宫的概率.四舍五入保留3位小数. 输入样例 4 3 3 2 .$. A#B A#C @@@ 143 37 335 85 9 ...

  6. CF1398D Colored Rectangles (记忆化搜索DP)

    数据范围只有200,所以我们可以用O(n3)O(n^3)O(n3)的暴力DP 闫氏DP分析法用着是真的爽 #include<cstdio> #include<algorithm> ...

  7. BZOJ3769:BST again(记忆化搜索DP)

    Description 求有多少棵大小为n的深度为h的二叉树.(树根深度为0:左右子树有别:答案对1000000007取模) Input 第一行一个整数T,表示数据组数. 以下T行,每行2个整数n和h ...

  8. POJ1088 滑雪题解+HDU 1078(记忆化搜索DP)

    Description Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你.Michael想知道 ...

  9. Pearls POJ - 1260(区间记忆化搜索)

    题意: n件物品,给出数量和价格,(注意数量和价格都是升序给出的这个是能DP的关键),要买掉所以商品 对于每类物品,所需要的价格是(a[i]+10)*p[i] ,即要多买10件,也可以把价格低的物品合 ...

  10. 【HDU - 1078】FatMouse and Cheese (记忆化搜索dp)

    题干: FatMouse has stored some cheese in a city. The city can be considered as a square grid of dimens ...

最新文章

  1. 工作10年从大公司离职去小公司当CTO,被同事鄙视竟然不回netty
  2. 商汤提基于贪心超网络的One-Shot NAS,达到最新SOTA | CVPR 2020
  3. 机器学习(四)——损失函数
  4. 深入浅出python机器学习_8.3_神经网络实例_手写识别_MNIST数据集的使用
  5. cassandra本地连接失败_无法连接到本地Cassandra实例?
  6. python 哪些项目_哪些Python开源项目比较好
  7. 伯克利2019深度学习课程—李沐及其亚马逊同事一起讲述(内附视频链接及PDF下载)
  8. Linux网络处理“零拷贝”技术mmap()内核进程间通信设计8086分页管理——摆在一起来谈谈...
  9. linux shell 递归统计代码行数
  10. 2015年国民经济和社会发展统计公报
  11. 纯前端导出PDF分页截取问题处理
  12. ONVIF系列——Onvif协议介绍
  13. ZDM按横断面水位线河道开挖
  14. android 8.0手机无法更新版本,微信8.0安卓机怎么安装更新 安卓微信更新不了8.0解决办法一览...
  15. 读博太孤独?一个人的苦行!
  16. 工作人员做好项目协调服务器,项目团队协作做好三件事
  17. HTML5期末大作业:网页设计——小米商城官网首页(1页) HTML+CSS+JavaScript web期末作业设计网页_清新淡雅个人网页大学生网页设计作业成品
  18. 简单的爬取某租房网站租房信息并存入MySQL数据库
  19. java libraries在哪_java.library.path在哪?
  20. echart 时间滚动_echarts x,y轴数据太长自动滚动(每次只显示固定数量,定时滚动显示其它)...

热门文章

  1. [CTF][Web][PHP][JavaScript]弱类型问题
  2. [Leetcode][第718题][JAVA][最长重复子数组][动态规划][滑动窗口][暴力]
  3. mysql安装条款_mysql 安装注意
  4. redis存储数据类型_Redis与Memcahe的区别最全整理
  5. 列名 userid 不明确。 表结构_那些你不知道的表结构设计思路
  6. java类与对象实验报告心得体会_第四周课程总结与实验报告(Java简单类与对象)...
  7. c#日期转换周几_Java时间与日期
  8. snmp获取交换机日志_日志审计系统和数据库审计系统的区别
  9. mysql重连服务器失败_java – MySQL连接器错误“服务器时区值中...
  10. nginx 怎么重新编译安装mysql,centos 下 编译安装 nginx + mysql + php 服务