当青训营遇上码上掘金
主题 3:寻友之旅 | C++ 菜鸟逻辑硬解版本!
小青要找小码去玩,他们的家在一条直线上,当前小青在地点 N ,小码在地点 K (0≤N , K≤100 000),并且小码在自己家原地不动等待小青。小青有两种交通方式可选:步行和公交。
步行:小青可以在一分钟内从任意节点 X 移动到节点 X-1 或 X+1
公交:小青可以在一分钟内从任意节点 X 移动到节点 2×X (公交不可以向后走)
请帮助小青通知小码,小青最快到达时间是多久?
输入: 两个整数 N 和 K
输出: 小青到小码家所需的最短时间(以分钟为单位)
说明:本人算法菜鸟一枚,欢迎路过大神指正~
下面是代码解决方案
初代版本解法(错误解法):
不想看错误初代版本的小伙伴可以看下面的正解。
思路
①首先判断n与k的值,有下面两种情况
- 当n>k时,那么小青只能是向左边慢慢移动,只能(X-1)移动,所以小青最快到达小码的地方需要的最短时间 minTime = n-k.
- 当n<k时,小青向右边走,小青可以选择两种走法,在这个解法中,我选择的是,使用一个while循环来判断小青 n<=k ,当在这个范围内,小青可以每次行走都是2X的方式,当while循环判断n<=k这个条件不满足的时候,我们就跳出循环,此时我们知道n和minTime都多执行了一次操作,在下面的代码中,使用if条件判断(n!=k),在if语句中书写n = n/2,minTime = minTime - 1,剩下的minTime则是选择走路到达,故最后的minTime = minTime + temp.
代码
using namespace std;
#include<iostream>
int main(){
int minTime = 0;
int n, k;
cin >> n >> k;
cout<<"n:"<<n<<endl;
cout<<"k:"<<k<<endl;
if(n>k){
//如果n>k的话,不能坐公交,因为公交不能倒退,所以只能选择步行。
minTime = n - k;
}else{
//n<k 的情况下,可以选择坐公交或者步行
//先选择坐公交 是节省时间的方式
while(n <= k){
//这种情况包含n恰好等于k的情况
n = n*2;
minTime++;
if(n == k){
cout<<"最短时间为:"<<minTime<<endl;
return 0;
}
}
if(n != k){
n = n/2;
minTime = minTime-1;
int temp = k - n;//剩余的部分选择步行到达
minTime = minTime + temp;
}
}
cout<<"最短时间为:"<<minTime<<endl;
//此方法是不严谨的方法
//案例① 输入 1 8
// 输出 3 -----正确答案
//案例② 输入 1 14
// 输出 9 -----错误答案
//错误原因:最短时间应该是5 过程是1-2-4-8-7-14 ,花费5秒钟
//
return 0;
}
初代代码版本参考这位同学的,不过他的也是错误的。 juejin.cn/post/718778…
最终成功版本:
思路 ①首先判断n与k的值,有下面两种情况(关键看n<k时的操作)
-
当n>k时,那么小青只能是向左边慢慢移动,只能(X-1)移动,所以小青最快到达小码的地方需要的最短时间 minTime = n-k.
-
当n<k时,开始我先是将n与k的值进行处理,将n的值和k的值从奇数变成偶数,方便我们的操作。
A.处理n(左端):当n%2!=0时,表示n是奇数,我们需要将n进行处理,变为偶数,此时操作为:n = n * 2;,minTime = minTime+1;在这个处理操作的if语句中同时在添加两个if判断,如果if(n==k),就直接输出cout<<minTime<<endl;如果(n>k),说明n * 2之后越界了,n = n/2;minTime = k-n;然后直接输出minTime就好。
B.处理k(右端):如果k是奇数-1,然后再/2 ,下面通过一个if(n*2<=k)来判断并且保证k是在n的右边的,接下来再判断k是奇数还是偶数,然后执行相应的操作,若是奇数k-1,若是偶数k/2,慢慢逼近n最终得到结果!
整体的算法思想 从k(右端开始倒退),k每次除以2,当k是奇数则-1,minTime++;然后k/2继续操作,目的就是遇到奇数就变偶数,遇到偶数除以二,以此类推,慢慢从右端逼近左端,即k慢慢逼近n,最后求出来的minTime就是最短时间。同时,如果左端n开始是奇数,那么直接给他×2变偶数就行,当成新的n,minTime同时++即可!
代码
using namespace std;
#include<iostream>
int main(){
int n, k;
cin >> n >> k;
cout<<"n:"<<n<<endl;
cout<<"k:"<<k<<endl;
int minTime = 0;//最少时间
if (n > k) {
//如果n>k的话 就说明不能坐公交,因为公交不能倒退,所以只能选择步行。
minTime = n - k;
} else if (n < k) {
//如果n<k的话 就说明可以公交或者步行
//先处理左端 例如n是奇数的话,就给他*2,变为偶数
if(n%2!=0){
n = n*2; //之后计算距离就从n*2开始计算 minTime+1就行
minTime = minTime+1;
if(n==k){
cout<<minTime<<endl;
return 0;
}
else if(n>k){ //n*2之后越界了 n比k大
//撤回刚才*2的操作
n = n/2;
minTime = k-n;
cout<<minTime<<endl;
return 0;
}
}
//右端k也要处理,如果k是奇数-1,然后再/2
while(n!=k){
if(n*2<=k){
if(k%2!=0){
k = k-1;
minTime++;
}
else{
k = k/2;
minTime++;
}
}
else{
minTime =minTime + k - n;
break;
}
}
cout<<minTime<<endl;
return 0;
}
// cout<<"最短时间:"<<minTime<<endl;
return 0;
}