当青训营遇见码上掘金
- 主题三:寻友之旅
小青要找小码去玩,他们的家在一条直线上,当前小青在地点 N ,小码在地点 K (0≤N , K≤100 000),并且小码在自己家原地不动等待小青。小青有两种交通方式可选:步行和公交。
步行:小青可以在一分钟内从任意节点 X 移动到节点 X-1 或 X+1
公交:小青可以在一分钟内从任意节点 X 移动到节点 2×X (公交不可以向后走)
请帮助小青通知小码,小青最快到达时间是多久?
输入: 两个整数 N 和 K
输出: 小青到小码家所需的最短时间(以分钟为单位)
分析
这是一个求最短路径问题,可以使用动态规划来做。
首先,当小码的位置K小于小青的位置N时,此时是最简单的情况,小青只能步行到达小码家。
接着,若小码的位置大于小青,利用动态规划的递归思想。
-
判断当前位置i是否是偶数节点,若是,则利用MinTime[i]=Min(MinTime[i-1]+1, MinTime[i/2]+1)进行判断,前面两个公式分别代表步行和公交两种交通方式。
-
若是奇数节点,则先判断乘坐公交的两种方式Bustime=Min(MinTime[(i-1)/2]+2, MinTime[(i+1)/2]+2),其中加2是坐公车到达偶数节点的时间(1)加上到当前节点的时间(1)
源代码
package main
import (
"fmt"
)
// 动态规划方法
// 当小青位置N在小码位置前面时,只能步行
// 反之,需要决策步行还是公交,利用公式MinTime[i]=Min(MinTime[i-1]+1,MinTime[(i+N)/2]+1)
func FindMinTime(N int, K int) int {
if N >= K {
return N - K
} else {
MinTime := make([]int, K+1)
MinTime[N] = 0
for i := N - 1; i >= 0; i-- {
MinTime[i] = N - i
}
for i := N + 1; i <= K; i++ {
if i%2 == 0 {
MinTime[i] = min(MinTime[i-1]+1, MinTime[i/2]+1)
} else {
//该点是奇数节点,判断前一个及后一个偶数节点的公交时间
BusTime := min(MinTime[(i-1)/2], MinTime[(i+1)/2]) + 2
MinTime[i] = min(MinTime[i-1]+1, BusTime)
}
}
return MinTime[K]
}
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
func main() {
var N, K int
fmt.Scan(&N, &K)
fmt.Println(FindMinTime(N, K))
}
实验结果