【LeetCode】1654. Minimum Jumps to Reach Home 到家的最少跳跃次数

【LeetCode】1654. Minimum Jumps to Reach Home 到家的最少跳跃次数_第1张图片【LeetCode】1654. Minimum Jumps to Reach Home 到家的最少跳跃次数_第2张图片

BFS.
坑:

  1. 因为不能后跳2次,通过-b往回跳的点,依然可以试图利用+a走一次。因为通过+a走到的点既能前跳又能后跳,不用再遍历了;而通过-b走到的点只能前跳,所以可能的情况下还是要通过+a走一次探索一下后跳的可能性。由于坐标一定是非负的,这里我用负数来表示某坐标是通过后跳走到的,这样就和前跳分开记录visited了。
  2. 可以把visited和forbid用一个set记录
  3. 由于x轴无限长,有可能无限尝试都得不到-1,尤其是在a的情况下。在a>b的情况下容易证明最远走x+b就可以了。而a的时候的尝试上限一直不知道怎么算……leetcode题解里通用的threshold是6000,也不知道咋来的。

    虽然有大佬给了证明,但是他证明出来的阈值是 max ⁡ ( max ⁡ ( F ) + a + b , x + b ) \max(\max(F)+a+b,x+b) max(max(F)+a+b,x+b),但是最后算具体阈值的时候套用的Fab的上限值去算的threshold,按 max ⁡ ( F ) + a + b \max(F)+a+b max(F)+a+b的上限去算的,所以是6000。
    但是,比如说121步的那个testcase:

    [162,118,178,152,167,100,40,74,199,186,26,73,200,127,30,124,193,84,184,36,103,149,153,9,54,154,133,95,45,198,79,157,64,122,59,71,48,177,82,35,14,176,16,108,111,6,168,31,134,164,136,72,98]
    29
    98
    80
    

    我自己把path打出来看过:

    [80, 51, -22, 120, -91, 189, -160, 258, -229, 327, -298, 396, -367, 465, -436, 534, -505, 603, -574, 672, -643, 741, -712, 810, -781, 879, -850, 948, -919, 1017, -988, 1086, -1057, 1155, -1126, 1224, -1195, 1293, -1264, 1362, -1333, 1431, -1402, 1500, -1471, 1569, -1540, 1638, -1609, 1707, -1678, 1776, -1747, 1845, -1816, 1914, 1885, 1856, 1827, 1798, 1769, 1740, 1711, 1682, 1653, 1624, 1595, 1566, 1537, 1508, 1479, 1450, 1421, 1392, 1363, 1334, 1305, 1276, 1247, 1218, 1189, 1160, 1131, 1102, 1073, 1044, 1015, 986, 957, 928, 899, 870, 841, 812, 783, 754, 725, 696, 667, 638, 609, 580, 551, 522, 493, 464, 435, 406, 377, 348, 319, 290, 261, 232, 203, 174, 145, 116, 87, 58, 29]
    

    最大值到达1914,而按他公式的算法阈值仅有327。所以这一番推导其实对特定testcase是不成立的,感觉只是用上限刚好算对了阈值而已……

class Solution:
    def minimumJumps(self, forbidden: List[int], a: int, b: int, x: int) -> int:        
        forbid = set(forbidden)
        f = max(forbid)
        for v in forbidden:
            forbid.add(-v)

        q1 = deque()
        q1.append(0)    # -i means jumped from i+b
        step = 0
        forbid.add(0)
        while q1:
            # print(step, q1)
            q2 = deque()
            for v in q1:
                i = abs(v)
                if i == x:
                    return step
                if i+a < 6000 and i+a not in forbid:
                    q2.append(i+a)
                    forbid.add(i+a)
                if v > 0 and i-b >= 0 and b-i not in forbid:
                    q2.append(-i+b)
                    forbid.add(b-i)
            q1 = q2
            step += 1
        return -1

你可能感兴趣的:(Leetcode,leetcode,算法,职场和发展)