青训营主题创作活动 主题 3:寻友之旅(Golang 实现)

56 阅读2分钟

当青训营遇上码上掘金

描述

小青要找小码去玩,他们的家在一条直线上,当前小青在地点 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 判断