当青训营遇上码上掘金会发生什么有趣的事情呢?
寻友之旅
主题介绍:
小青要找小码去玩,他们的家在一条直线上,当前小青在地点 N ,小码在地点 K (0≤N , K≤100 000),并且小码在自己家原地不动等待小青。小青有两种交通方式可选:步行和公交。
步行:小青可以在一分钟内从任意节点 X 移动到节点 X-1 或 X+1
公交:小青可以在一分钟内从任意节点 X 移动到节点 2×X (公交不可以向后走)
输入: 两个整数 N 和 K
输出: 小青到小码家所需的最短时间(以分钟为单位)
思路
阅读完本题后,最容易想到的就是可以通过贪心策略来寻求最小时间。解法复杂度为O(logn),当然其他解法可能也有,不过应该没有更优的复杂度。
此题贪心的关键在于分析最后的临界情况,最后小青到达小码的家有三种方式:
- 从左侧步行到达
- 从右侧步行到达
- 公交直接到达
所以分为以下两个贪心阶段:
- 当
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)
}
一般题目解法都不唯一,若有不足之处,欢迎交流讨论。