当青训营遇上码上掘金
描述
小青要找小码去玩,他们的家在一条直线上,当前小青在地点 N ,小码在地点 K (0≤N , K≤100 000),并且小码在自己家原地不动等待小青。小青有两种交通方式可选:步行和公交。
步行:小青可以在一分钟内从任意节点 X 移动到节点 X-1 或 X+1
公交:小青可以在一分钟内从任意节点 X 移动到节点 2×X (公交不可以向后走)
请帮助小青通知小码,小青最快到达时间是多久?
输入
两个整数 N 和 K
输出
小青到小码家所需的最短时间(以分钟为单位)
来源 | 提交方式
本题源自 NOI 2971,提交链接:noi.openjudge.cn/ch0205/2971… 或 www.acwing.com/problem/con…
思路
本题是较为基础的 BFS 练习题,每次搜索都对应着三种操作,即 X -> X + 1, X -> X - 1, X -> X * 2, 由 BFS 搜索的性质可知,最先搜索到结点 k 的搜索次数即为小青最快到达时间
Golang 快读
这里介绍一下 Golang 的快读,通过 bufio 包的 Scanner 结构体的方法读取输入,会比使用 fmt.Scanf 速度快上很多,对于时限要求较高的算法题,使用快读是很有必要的
代码
package main
import (
"bufio"
"fmt"
"os"
"strconv"
)
var sc = bufio.NewScanner(os.Stdin)
const N int = 100005
func main() {
sc.Buffer(make([]byte, 500000*1+1), 500000)
sc.Split(bufio.ScanWords)
n, k := nextInt(), nextInt()
distance := make([]int, N)
q := make([]int, 0, N)
q = append(q, n)
distance[n] = 0
for len(q) > 0 {
x := q[0]
q = q[1:]
if x == k {
break
}
dir := [3]int{-1, 1, x}
for i := 0; i < 3; i++ {
next := x + dir[i]
if next >= 0 && next < N && next != n && distance[next] == 0 {
distance[next] = distance[x] + 1
q = append(q, next)
}
}
}
fmt.Println(distance[k])
}
func nextInt() int {
sc.Scan()
i, e := strconv.Atoi(sc.Text())
if e != nil {
panic(e)
}
return i
}
其中 distance[i] 是小青到达 i 点的最快时间,然后就是 BFS 的模板了,注意这里使用 dir 数组使编码更为简单,但创建数组的开销会对时限有着一定影响,如果追求速度,可不使用 dir 数组,在 for i := 0; ... 循环中添加 if 判断