当青训营遇上码上掘金
1. 背景说明
题目意思很明确,抽象出来就是横轴上有两个点A和点B,从A到B每一步都有两种方案选择:一是步行,步行只能移动一个单位长度,可以前进或者后退;二是坐公交,每次可以移动一倍的当前距离,只能前进。刚开始看到这个条件的时候我以为公交车可以中途下人,不过后来想了一下如果可以下人的话还需要步行干啥,直接坐公交到B点不就行了,显然公交车中途是不能停车的!
2. 方法说明
采用贪心思想,想要尽快到达B点,当前坐标下的最优选择就是乘坐公交车(当然可能到不了,也可能刚到,也可能错过终点需要往回走)。
- 2 * N < M:到不了终点,我们更新N为2N,
最短时间+1,继续判断条件1 - 2 * N = M:恰好到达终点,我们更新最短时间
+1后,直接输出结果 - 2 * N > M:这个时候N < M < 2 * N。此时我们假设终点位于X,那么如果步行的话就需要X - N的时长,如果坐车的话,到达2N点后需要往回走,这个时候需要1 + 2N - X的时长,两个时长作差:
T = (X - N) - (2N + 1 - X) = 2X - 3N - 1,若:- T > 0,则有X > 1.5N + 0.5,此时坐公交再往回走所花费的时间是最少的,这个时候我们更新最短时间
先+1(坐公交车),然后再+2N-X(往回走的时间) - T = 0,这个时候X = 1.5N + 0.5,如果N为偶数的话这种情况不存在,如果N为奇数的话这种情况存在,此时坐公交和步行是一样的时间,我们只需要更新最短时间
+X-N - T < 0,则有X < 1.5N + 0.5,此时步行花费的时间是最短的,我们同样更新最短时间
+X-N
- T > 0,则有X > 1.5N + 0.5,此时坐公交再往回走所花费的时间是最少的,这个时候我们更新最短时间
3. Java代码(老实话这么多if else是不是能优化一点emmm...)
import java.util.*;
public class Main {
public static void main(String[] args) {
int N, M;
Scanner scanner = new Scanner(System.in);
N = scanner.nextInt();
M = scanner.nextInt();
int minTime = 0; // 最小时间从0开始
while (true) {
if (2 * N < M) {
minTime++;
N *= 2;
} else if (2 * N == M) {
minTime++;
break;
} else {
if (1.5 * N < M) {
minTime++; // 先坐公交
minTime += 2 * N - M; // 然后回头步行到终点
} else {
minTime += M - N; // 直接步行走到终点
}
break;
}
}
System.out.println(minTime);
}
}