「青训营 X 码上掘金」主题 3:寻友之旅 BFS DFS

159 阅读2分钟

「青训营 X 码上掘金」主题 3:寻友之旅 BFS DFS

当青训营遇上码上掘金
主题 3:寻友之旅
语言: Go

小青要找小码去玩,他们的家在一条直线上,当前小青在地点 N ,小码在地点 K (0≤N , K≤100 000),并且小码在自己家原地不动等待小青。小青有两种交通方式可选:步行和公交。
步行:小青可以在一分钟内从任意节点 X 移动到节点 X-1 或 X+1
公交:小青可以在一分钟内从任意节点 X 移动到节点 2×X (公交不可以向后走)

请帮助小青通知小码,小青最快到达时间是多久?
输入: 两个整数 N 和 K
输出: 小青到小码家所需的最短时间(以分钟为单位)

一般解答

package main

import "fmt"

func main() {
    // 输入n k
	var n, k int
	_, err := fmt.Scanf("%d%d", &n, &k)
	if err != nil {
		return
	}
	// 初始化计数器并循环求解
	count := 0
	for n != k {
		if k > n {
			if k%2 == 0 {
				k = k / 2
			} else {
				k = k - 1
			}
			count++
		} else {
			k = k + 1
			count++
		}
	}
	// 输出计数器结果
	fmt.Println(count)
}

BFS解答

func main() {
	// 初始化
	var n, k int
	fmt.Scanf("%d%d", &n, &k)
	start := Node{n: n, minute: 0}

	// 初始化
	queue := []Node{start}

	// 初始化
	visited := make(map[int]bool)

	// 初始化
	target := k

	// BFS
	for len(queue) > 0 {
		// Get
		node := queue[0]
		queue = queue[1:]

		// Check
		if _, ok := visited[node.n]; ok {
			continue
		}

		// Mark
		visited[node.n] = true

		// Check
		if node.n == target {
			fmt.Println("Found target in", node.minute, "minutes")
			break
		}

		// Add
		queue = append(queue, Node{n: node.n - 1, minute: node.minute + 1})
		queue = append(queue, Node{n: node.n + 1, minute: node.minute + 1})
		queue = append(queue, Node{n: node.n * 2, minute: node.minute + 1})
	}
}

DFS解答

package main

import "fmt"

func dfs(n, k int, depth int) int {
	if n == k {
		return depth
	}
	if n > k {
		return dfs(n-1, k, depth+1)
	}
	if n < k {
		return dfs(n+1, k, depth+1)
	}
	return dfs(n*2, k, depth+1)
}

func minStepsToK(n, k int) int {
	if n == k {
		return 0
	}
	minSteps := dfs(n+1, k, 1)
	minSteps = min(minSteps, dfs(n-1, k, 1))
	minSteps = min(minSteps, dfs(n*2, k, 1))
	return minSteps
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

func main() {
	var N, K int
	_, err := fmt.Scanf("%d%d", &N, &K)
	if err != nil {
		return
	}
	minutes := minStepsToK(N, K)
	fmt.Println(minutes)
}