寻友之旅主题创作「青训营 X 码上掘金」

61 阅读2分钟

当青训营遇上码上掘金会发生什么有趣的事情呢?

寻友之旅

主题介绍:

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

输入: 两个整数 N 和 K
输出: 小青到小码家所需的最短时间(以分钟为单位)

思路

阅读完本题后,最容易想到的就是可以通过贪心策略来寻求最小时间。解法复杂度为O(logn),当然其他解法可能也有,不过应该没有更优的复杂度。

此题贪心的关键在于分析最后的临界情况,最后小青到达小码的家有三种方式:

  1. 从左侧步行到达
  2. 从右侧步行到达
  3. 公交直接到达

所以分为以下两个贪心阶段:

  • N * 2 小于或等于 K 时,必然是坐公交最节省时间。
  • 当再坐一次公交会大于K时,这个临界状态有两个选择:
    • 从左侧直接步行到达
    • 再坐一次公交,从右侧步行到达

Code

C++

#include<bits/stdc++.h>

using namespace std;

int main()
{   
    int n,k;
    cin>>n>>k;
    int ans = 0;
    while(n*2 <= k){  //尽量坐公交
        n = n*2;
        ans++;
    } 
    ans += min( k - n, n * 2 -k + 1 ); //临界状态
    cout<<ans<<"\n";
    return 0;
}

Go

package main

import "fmt"

func main() {

    n, k, ans := 0, 0, 0
    fmt.Scanf("%d %d", &n, &k)
    for n*2 <= k {
        n = n * 2
        ans++
    }
    if k-n < n*2-k+1 {
        ans += k - n
    } else {
        ans += n*2 - k + 1
    }
    fmt.Printf("%d", ans)
}

一般题目解法都不唯一,若有不足之处,欢迎交流讨论。