• 动态规划-Help JimmyV2


    完成的游戏:场景中包括多个长度和高度各不相同的平台。地面是最低的平台,高度为零,长度无限。
    Jimmy老鼠在时刻0从高于所有平台的某处开始下落,它的下落速度始终为1米/秒。当Jimmy
    落到某个平台上时,游戏者选择让它向左还是向右跑,它跑动的速度也是1米/秒。当Jimmy
    跑到平台的边缘时,开始继续下落。Jimmy每次下落的高度不能超过MAX米,不然就会摔死,
    游戏也会结束。设计一个程序,计算Jimmy到地面时可能的最早时间。

    输入数据
    第一行是测试数据的组数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恰好落在某个平台的
    边缘,被视为落在平台上。所有的平台均不重叠或相连。测试数据保Jimmy
    一定能安全到达地面。

    输出要求:对输入的每组测试数据,输出一个整数,Jimmy到地面时可能的最早时间。
    输入样例
    1
    3 8 17 20
    0 10 8
    0 10 13
    4 14 3
    输出样例
    23


    思路:递归实现
    求到达地面的最短时间,将初始位置看作一个平台,地面也看作一个平台,
    对各个平台的高度进行排序,用递归来做用最大的一直往下找到地位的最短时间
    为了提高效率,利用leftMinList, rightMinList两个列表分别记录平台
    左右方向下落的最小时间

    python算法实现:
     1 # 二维列表的列索引含义:0表示平台左边坐标、1表示平台右边坐标、2表示平台的高度
     2 plat_list = []
     3 # 递归中为了避免重复计算,提高运算效率,需存储每个i平台左右下落的最小时间
     4 # 存储i平台左右下落的最小时间,-1表示没有计算过,
     5 leftMinList, rightMinList = [], []
     6 # 定义无穷大
     7 inf = float('inf')
     8 N, MaxHeight = 0, 0
     9 
    10 
    11 # 计算从平台i到地面的最短时间,往左往右都需要计算才能找到最小值
    12 # jimmy从出发下落到第1块板有可能走左边也可能走右边
    13 # N表示平台的个数
    14 def minDropTime(i, isGoLeft):
    15     global plat_list, N, MaxHeight, leftMinList, rightMinList
    16     x = 0
    17     y = plat_list[i][2]  # 当前点的高度
    18     # 如果是去左边,就走到左边边上,如果去右边,就走到右边边上
    19     if isGoLeft:
    20         x = plat_list[i][0]
    21     else:
    22         x = plat_list[i][1]
    23     # 查找如果从左边或者右边下落,是否能到达下一块板
    24     # k记录可以下落板的编号
    25     k = 0
    26     for j in range(i + 1, N + 1):
    27         # 如果x落在下一块板的中间,则说明可以从i下落到j板
    28         if plat_list[j][0] <= x <= plat_list[j][1]:
    29             k = j
    30             break
    31     # 说明往i下面没有板可以下落
    32     if k == 0:
    33         if y > MaxHeight:
    34             return inf
    35         else:
    36             return y
    37     else:  # 有可以下落的板
    38         if y - plat_list[k][2] > MaxHeight:
    39             return inf
    40         else:
    41             # =-1,说明该平台下落的最小时间没有计算过
    42             if leftMinList[k] == -1:
    43                 leftMinList[k] = minDropTime(k, True)
    44             if rightMinList[k] == -1:
    45                 rightMinList[k] = minDropTime(k, False)
    46             # 如果计算过k平台下落的最小时间,则可以直接计算,不需要重新递归提高效率
    47             # 返回平台i往左或者右方向下落的最小值=高度差+min(走k平台左端最小时间,走k平台右端最小时间)
    48             return (y - plat_list[k][2]) + min(x - plat_list[k][0] + leftMinList[k],
    49                                                plat_list[k][1] - x + rightMinList[k])
    50 
    51 
    52 def main():
    53     global plat_list, N, MaxHeight, leftMinList, rightMinList
    54     # t表示测试数据的组数
    55     t = int(input())
    56     while t > 0:
    57         # N: 平台数目 X, Y: 开始下落位置坐标 MAX: 一次下落最大高度
    58         N, X, Y, MaxHeight = 0, 0, 0, 0
    59         N, X, Y, MaxHeight = map(int, input().split())
    60         # 记录从该平台左边下落的最小时间
    61         leftMinList = [-1 for i in range(N + 1)]
    62         # 记录从该平台右边下落的最小时间
    63         rightMinList = [-1 for i in range(N + 1)]
    64         # 平台的二维数组列表
    65         plat_list = [[0 for i in range(3)] for i in range(N + 1)]
    66 
    67         # 把jimmy的出发点也当做一个平台,即递归的出发点
    68         plat_list[0][0], plat_list[0][1], plat_list[0][2] = X, X, Y
    69         for i in range(1, N + 1):
    70             plat_list[i] = [int(n) for n in input().split()]  # 输入各平台参数
    71         # 对平台按高度排序,sorted这个函数要重新覆盖原来的列表内容才会排序
    72         plat_list = sorted(plat_list, key=(lambda x: x[2]), reverse=True)
    73         # [[8, 8, 17], [0, 10, 13], [0, 10, 8], [4, 14, 3]]
    74         min_value = minDropTime(0, True)
    75         print("Jimmy到底地面时可能的最早时间为:%d" % min_value)
    76         t = t - 1
    77 
    78 
    79 if __name__ == '__main__':
    80     main()
     
  • 相关阅读:
    南邮NOJ整除的尾数
    【HDOJ】2844 Coins
    【HDOJ】2546 饭卡
    【HDOJ】1031 Design T-Shirt
    【HDOJ】1983 Kaitou Kid
    【HDOJ】2612 Find a way
    【原创】如何构建MIPS交叉编译工具链
    【HDOJ】1239 Calling Extraterrestrial Intelligence Again
    【Python Network】使用DOM生成XML
    【HDOJ】2602 Bone Collector
  • 原文地址:https://www.cnblogs.com/an-wl/p/13056079.html
Copyright © 2020-2023  润新知