寻友之旅
当青训营遇上码上掘金
我选择的是主题3,原文地址:「青训营 X 码上掘金」主题创作活动入营版 开启! - 掘金 (juejin.cn)
主题 3:寻友之旅
小青要找小码去玩,他们的家在一条直线上,当前小青在地点 N ,小码在地点 K (0≤N , K≤100 000),并且小码在自己家原地不动等待小青。小青有两种交通方式可选:步行和公交。 步行:小青可以在一分钟内从任意节点 X 移动到节点 X-1 或 X+1 公交:小青可以在一分钟内从任意节点 X 移动到节点 2×X (公交不可以向后走)
请帮助小青通知小码,小青最快到达时间是多久? 输入: 两个整数 N 和 K 输出: 小青到小码家所需的最短时间(以分钟为单位)
思路
采用动态规划解决这个问题,对于出发点N和目标点K,有以下三种情况:
- N < K,使用动态规划解法;
- N = K,直接返回0;
- 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之后的点,然后再倒退的情况,所以我们要迭代更新,找到最终解的最小值,代码如下: