寻友记 | 青训营主题创作

83 阅读2分钟

当青训营遇上码上掘金

1. 背景说明

题目意思很明确,抽象出来就是横轴上有两个点A和点B,从A到B每一步都有两种方案选择:一是步行,步行只能移动一个单位长度,可以前进或者后退;二是坐公交,每次可以移动一倍的当前距离,只能前进。刚开始看到这个条件的时候我以为公交车可以中途下人,不过后来想了一下如果可以下人的话还需要步行干啥,直接坐公交到B点不就行了,显然公交车中途是不能停车的!


2. 方法说明

采用贪心思想,想要尽快到达B点,当前坐标下的最优选择就是乘坐公交车(当然可能到不了,也可能刚到,也可能错过终点需要往回走)。

  1. 2 * N < M:到不了终点,我们更新N为2N,最短时间+1继续判断条件1
  2. 2 * N = M:恰好到达终点,我们更新最短时间+1后,直接输出结果
  3. 2 * N > M:这个时候N < M < 2 * N。此时我们假设终点位于X,那么如果步行的话就需要X - N的时长,如果坐车的话,到达2N点后需要往回走,这个时候需要1 + 2N - X的时长,两个时长作差:T = (X - N) - (2N + 1 - X) = 2X - 3N - 1,若:
    1. T > 0,则有X > 1.5N + 0.5,此时坐公交再往回走所花费的时间是最少的,这个时候我们更新最短时间先+1(坐公交车),然后再+2N-X(往回走的时间)
    2. T = 0,这个时候X = 1.5N + 0.5,如果N为偶数的话这种情况不存在,如果N为奇数的话这种情况存在,此时坐公交和步行是一样的时间,我们只需要更新最短时间+X-N
    3. T < 0,则有X < 1.5N + 0.5,此时步行花费的时间是最短的,我们同样更新最短时间+X-N

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);
    }
}