当青训营遇上码上掘金
题目
主题 3:寻友之旅
小青要找小码去玩,他们的家在一条直线上,当前小青在地点 N ,小码在地点 K (0≤N , K≤100 000),并且小码在自己家原地不动等待小青。小青有两种交通方式可选:步行和公交。 步行:小青可以在一分钟内从任意节点 X 移动到节点 X-1 或 X+1 公交:小青可以在一分钟内从任意节点 X 移动到节点 2×X (公交不可以向后走)
请帮助小青通知小码,小青最快到达时间是多久? 输入: 两个整数 N 和 K 输出: 小青到小码家所需的最短时间(以分钟为单位)
测试用例:
输入:
2 2048
输出:
10
思路:
本体要求得出从当前地点到目标地点的最短时间。看到最短时间的要求(求最值),首先想到动态规划。
因为求解动态规划的核心问题是穷举。因为要求最值,肯定要把所有可行的答案穷举出来,然后在其中找最值
第一步要明确状态和选择。
状态就是当前的路程距离,选择就是走路或者坐公交。
第二步要明确 dp 数组的定义。
按照动态规划的套路,可以给出如下定义:
dp[i] = x表示:当前地点的为 i 时,从地点 n 处到达此地 i 需要 x 分钟的时间。
根据这个定义,我们想求的最终答案就是dp[m],base case 就是 dp[0] = 0。
第三步,根据选择,思考状态转移的逻辑。
回想刚才的 dp 数组含义,可以根据「选择」对 dp[i] 得到以下状态转移:
如果选择步行,那么到达目的地,取决于上一个状态 dp[i-1]的时间,最终时间为之前的时间+1。
如果选择坐公交,那么到达目的地,取决于上一个状态 dp[i/2]的时间,最终时间为之前的时间+1。
第四步,把伪码翻译成代码,处理一些边界情况。
以下是我的 Java 代码,完全翻译了之前的思路,并处理了一些边界情况:
代码:
import java.util.Arrays;
import java.util.Scanner;
/*
小青要找小码去玩,他们的家在一条直线上,当前小青在地点 N ,小码在地点 K (0≤N , K≤100 000),并且小码在自己家原地不动等待小青。
小青有两种交通方式可选:步行和公交。
步行:小青可以在一分钟内从任意节点 X 移动到节点 X-1 或 X+1
公交:小青可以在一分钟内从任意节点 X 移动到节点 2×X (公交不可以向后走)
请帮助小青通知小码,小青最快到达时间是多久?
输入: 两个整数 N 和 K
输出: 小青到小码家所需的最短时间(以分钟为单位
*/
public class find_friend {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int m = scanner.nextInt();
if (m <= n){
System.out.println(n-m);
return;
}
int[] dp = new int[m+1];
for (int i = 0; i <= n; i++) {
dp[i] = n-i;
}
for (int i = n+1; i <= m; i++) {
if(i%2==0){
dp[i] = Math.min(dp[i-1]+1,dp[i/2]+1);
}else{
dp[i] = dp[i-1]+1;
}
}
System.out.println(dp[m]);
scanner.close();
}
}