寻友之旅 | 码上掘金

42 阅读2分钟

寻友之旅

当青训营遇上码上掘金

我选择的是主题3,原文地址:「青训营 X 码上掘金」主题创作活动入营版 开启! - 掘金 (juejin.cn)

主题 3:寻友之旅

小青要找小码去玩,他们的家在一条直线上,当前小青在地点 N ,小码在地点 K (0≤N , K≤100 000),并且小码在自己家原地不动等待小青。小青有两种交通方式可选:步行和公交。 步行:小青可以在一分钟内从任意节点 X 移动到节点 X-1 或 X+1 公交:小青可以在一分钟内从任意节点 X 移动到节点 2×X (公交不可以向后走)

请帮助小青通知小码,小青最快到达时间是多久? 输入: 两个整数 N 和 K 输出: 小青到小码家所需的最短时间(以分钟为单位)

思路

采用动态规划解决这个问题,对于出发点N和目标点K,有以下三种情况:

  1. N < K,使用动态规划解法;
  2. N = K,直接返回0;
  3. N > K,只能向后走(不行方式),答案也已经确定了。

对于情况2和情况3,我们可以归结为一种情况,直接返回N - K即可。

对于情况1的动态规划,首先定义dp数组的含义,定义dp[i]为从位置N到达位置i需要的最短时间,以位置N作为分割线,N左侧的数组dp[0..N-1]对应的是不行倒退的情况,从右往左进行递增初始化即可。

为什么还要考虑倒退的情况呢,因为后续计算bus方式的时间的时候,有可能会涉及到N点之前的dp值。

N右侧的数组dp[N+1..N]需要进行迭代更新:dp[i]=min(walkdp, busdp)

其中walkdp是通过走路方式的最短耗时,walkdp= dp[i - 1] + 1

busdp是通过公交方式的最短耗时,又分当前i是否为偶数的情况:

  • 如果是偶数 ,busdp = dp[i / 2] + 1
  • 如果是奇数,可以从(i + 1)/ 2处坐公交到i + 1处,再倒退一步,耗时dp[(i + 1) / 2] + 1;也可以从(i - 1)/ 2处坐公交到i - 1处,再倒退一步,耗时dp[(i - 1) / 2] + 1,最终busdp取二者最小值。

状态的分析到此位置,当i迭代更新到k之后的时候,可以开始构造解,因为有可能会出现先到达k之后的点,然后再倒退的情况,所以我们要迭代更新,找到最终解的最小值,代码如下: