青训营主题创作活动——主题3:寻友之旅

82 阅读2分钟

当青训营遇上码上掘金

题目:

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

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

解题思路:

小青到达K点存在两种情况:

  1. 正常到达
  2. 超过折返

正常到达中又存在选择问题,如果小青乘车之后,距离K点只剩下步行两次的路程,需要选择步行来到达K点。 只有当小青乘车加上折返的时间要小于小青直接步行到达K点的时间才会存在超过折返情况。 题目要求是求出到达K点最短时间,那么乘车肯定是优先选择(当N为0时不可乘车),当N乘车之后超过K点才需要我们判断决策是步行直接到达,还是超过折返。可以直接暴力解题

暴力法代码实现如下

package main

import "fmt"

func main() {
   var N, K int
   time := 0
   fmt.Scanln(&N, &K)
   if N < 0 || K > 100000 {
      return
   }

   for N != K {
      //未超过终点
      if N < K {
         N = max(N, K)
         println("N : ", N)
         time++
         println("time : ", time)
      }
      //超过终点
      if N > K {
         time += N - K
         println("time2 : ", time)
         break
      }
   }
   //输出结果
   fmt.Println(time)
}

// 未达到终点之前比较两种方式,谁移动更远
func max(X, K int) int {
   //步行距离更远时
   if X+1 > X*2 {
      return X + 1
   } else {
      //当乘车会超过终点
      if X*2 > K {
         time1 := K - X       //计算步行时间
         time2 := X*2 - K + 1 //计算乘车后步行返回K的时间
         //选择时间更短的方式
         if time1 < time2 {
            println("超过终点,选择步行")
            return X + 1
         } else {
            println("超过终点,选择乘车")
            return X * 2
         }
      } else { //乘车不会超过终点
         return X * 2
      }
   }
}