Codeforces D. Discrete Centrifugal Jumps

https://codeforces.com/contest/1407/problem/D
DP + 栈

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while (sc.hasNext()) {
            int n = Integer.parseInt(sc.nextLine());
            String[] arr = sc.nextLine().split(" ");
            int[] nums = new int[n];
            for (int i = 0; i < n; i++) {
                nums[i] = Integer.parseInt(arr[i]);
            }
            System.out.println(solve(n, nums));
        }
    }

    static int solve(int n, int[] h) {
        ArrayDeque<Integer> inc = new ArrayDeque<>();
        ArrayDeque<Integer> dec = new ArrayDeque<>();
        inc.push(0);
        dec.push(0);
        // dp[i] 表示从起点跳到下标 i 需要的最少跳跃次数
        int[] dp = new int[n];
        Arrays.fill(dp, Integer.MAX_VALUE);
        dp[0] = 0;
        for (int i = 1; i < n; i++) {
            // 相邻位置可以直接跳一次
            dp[i] = Math.min(dp[i], dp[i - 1] + 1);
            // V 字型区域可以跳过一段
            // 当前高度小于等于单调递增栈的栈顶元素 等于的时候主要是为了弹出前一个元素
            while (!inc.isEmpty() && h[i] <= h[inc.peek()]) {
                Integer pop = inc.pop();
                // 只有小于栈顶元素 并且左侧还有元素的情况下 才能跳跃
                if (!inc.isEmpty() && h[i] < h[pop]) {
                    dp[i] = Math.min(dp[i], dp[inc.peek()] + 1);
                }
            }
            inc.push(i);
            // 这部分的原理同上
            while (!dec.isEmpty() && h[i] >= h[dec.peek()]) {
                Integer pop = dec.pop();
                if (!dec.isEmpty() && h[i] > h[pop]) {
                    dp[i] = Math.min(dp[i], dp[dec.peek()] + 1);
                }
            }
            dec.push(i);
        }
        return dp[n - 1];
    }
}

你可能感兴趣的:(算法,java,数据结构)