当青训营遇上码上掘金
主题内容
-
小青要找小码去玩,他们的家在一条直线上,当前小青在地点 N ,小码在地点 K (0≤N , K≤100 000),并且小码在自己家原地不动等待小青。小青有两种交通方式可选:步行和公交。
步行:小青可以在一分钟内从任意节点 X 移动到节点 X-1 或 X+1
公交:小青可以在一分钟内从任意节点 X 移动到节点 2×X (公交不可以向后走)请帮助小青通知小码,小青最快到达时间是多久?
输入: 两个整数 N 和 K
输出: 小青到小码家所需的最短时间(以分钟为单位)
题解
bfs
首先将小青和小码的位置看作数轴,0为原点,则分为时所需时间;时,N下一步可到达的点有,,,则可以考虑用bfs求解最短距离的思想。每一个可达点可抽象为图中的一个点,每个点之间的距离为1,该题则转化为给定起点和终点,求最短距离。该算法的时间复杂度为.
代码(golang)
package main
import "fmt"
const N = 200010
func bfs(beg, end int) int {
var b [N]int //b[i]:从beg到i的最短耗时
queue := make([]int, 0)
queue = append(queue, beg) //入队
v := beg
for v != end {
v = queue[0]
queue = queue[1:] //出队
q1, q2, q3 := v-1, v+1, v*2
if 0 < q1 && q1 < 2*end && b[q1] == 0 {
b[q1] = b[v] + 1
queue = append(queue, q1)
}
if 0 < q2 && q2 < 2*end && b[q2] == 0 {
b[q2] = b[v] + 1
queue = append(queue, q2)
}
if 0 < q3 && q3 < 2*end && b[q3] == 0 {
b[q3] = b[v] + 1
queue = append(queue, q3)
}
}
return b[end]
}
func main() {
//小青在n,小码在k
var n, k int
fmt.Scanf("%d%d", &n, &k)
res := 0
if n <= k { //小青前进可乘公交可步行
res = bfs(n, k)
} else { //小青向后走只能步行
res += n - k
}
fmt.Printf("%d", res)
}
总结
该做法比较暴力,据测试当从0到100000时大概耗时3s+,抽象为图后,因为每个点之间的距离是1用dfs和bfs差不多,需要界定边界,因为乘公交时可达的位置,而每次走路只能到前进后退1,所以当下个可达点超过 了一定不是最优解。bfs可以不加边界,只判断到没到终点,因为一定可以到终点,且是最短耗时,但加上可以节省一点时空消耗,另外可达方式涉及不同的运算符,所以入队的时候写了三个判断,暂时没想到好的解决方法放到循环里。DP做法能力有限没想出来,待之后更(汗)。