算法-交替方向的最小路径代价III-Dijkstra最短路径算法

题目

给你两个整数 mn,表示一个网格的行数和列数。你的目标是到达单元格 (m - 1, n - 1)。同时给你一个二维整数数组 penalty

进入单元格 (i, j) 的代价为 (i + 1) * (j + 1)

你从单元格 (0, 0) 开始,最初需要支付其入口代价。进入 (0, 0) 后执行的行动从 1 开始编号。

在每次行动中,你可以移动到一个 相邻的单元格,或者在当前单元格等待。如果满足以下条件,则移动遵循奇偶性规则:

  • 奇数编号 的行动中,你向 或向 移动。
  • 偶数编号 的行动中,你向 或向 移动。

行动的代价由以下方式决定:

  • 如果你遵循奇偶性规则移动,只需支付目标单元格的入口代价。
  • 如果你在 违反 奇偶性规则的方向上移动,支付目标单元格的入口代价加上 penalty[i][j],其中 (i, j) 是你移动前所在的单元格。
  • 如果你在单元格 (i, j)等待 ,支付 penalty[i][j]

在每次移动或等待之后,行动编号增加 1。因此,无论是否支付了惩罚代价,所需遵循的奇偶性规则在每次行动后都会交替改变。

返回到达 (m - 1, n - 1) 所需的 最小总代价。

示例 1:

输入: m = 2, n = 2, penalty = \[5,3,1,4]

输出: 8

解释:

最优路径为:

  • 从单元格 (0, 0) 开始,入口代价为 (0 + 1) * (0 + 1) = 1
  • 行动 1 :向下移动到单元格 (1, 0),入口代价为 (1 + 1) * (0 + 1) = 2
  • 行动 2 :向右移动到单元格 (1, 1),入口代价为 (1 + 1) * (1 + 1) = 4,因为违反了偶数奇偶性规则,额外代价为 penalty[1][0] = 1

因此,总代价为 1 + 2 + 4 + 1 = 8

题解

思路:Dijkstra最短路径算法模版题,需要注意的是除了优先级队列,还需要一个最小值数组维护答案,举例:比如从A出发到C,有两条路径,A->C是权值是5,先A->B,全值是3,然后B->C,权值是4,按优先级队列,会先走A->B,再走B->C,权值和是7,但实际上是从A->C权值是5,权值最小,这就需要一个最小值数组,另外需要考虑的就是最小值数组维护的维度。

java 复制代码
class Solution {
    // 奇数下标 1,3 对应向右或向下
    // 偶数下标 0,2 对应向左或向上
    private static final int[][] DIRS = {{0, -1}, {0, 1}, {-1, 0}, {1, 0}}; // 左右上下

    private record Node(long d, int i, int j, int k) {
    }

    public long minCost(int m, int n, int[][] penalty) {
        long[][][] dis = new long[m][n][2];
        for (long[][] mat : dis) {
            for (long[] row : mat) {
                Arrays.fill(row, Long.MAX_VALUE);
            }
        }

        PriorityQueue<Node> pq = new PriorityQueue<>((a, b) -> Long.compare(a.d, b.d));

        // 支付 1 的入口代价
        dis[0][0][1] = 1;
        pq.offer(new Node(1, 0, 0, 1));

        while (true) {
            Node top = pq.poll();
            long d = top.d;
            int i = top.i;
            int j = top.j;
            int k = top.k;
            if (i == m - 1 && j == n - 1) {
                return d;
            }
            if (d > dis[i][j][k]) {
                continue;
            }
            int p = penalty[i][j];

            // 原地不动
            long newDis = d + p;
            if (newDis < dis[i][j][k ^ 1]) {
                dis[i][j][k ^ 1] = newDis;
                pq.offer(new Node(newDis, i, j, k ^ 1)); // k^1 切换行动编号的奇偶性
            }

            // 移动一步
            for (int idx = 0; idx < 4; idx++) {
                int x = i + DIRS[idx][0];
                int y = j + DIRS[idx][1];
                if (0 <= x && x < m && 0 <= y && y < n) {
                    // 如果 k 和 idx 的奇偶性不同,那么违反了奇偶性规则,需要额外支付 p 的代价
                    newDis = d + (x + 1) * (y + 1) + (idx % 2 ^ k) * p;
                    if (newDis < dis[x][y][k ^ 1]) {
                        dis[x][y][k ^ 1] = newDis;
                        pq.offer(new Node(newDis, x, y, k ^ 1)); // k^1 切换行动编号的奇偶性
                    }
                }
            }
        }
    }
}
相关推荐
午彦琳26 分钟前
2026.9.11
数据结构·python·算法
302wanger1 小时前
蛋炒饭周刊 · 第 1 期(2026-09-07至2026-09-11)
算法
shehuiyuelaiyuehao2 小时前
算法43,外观数列,模拟算法+双指针
java·算法
alphaTao2 小时前
LeetCode 每日一题 2026/9/7-2026/9/13
算法·leetcode
kanhaoning2 小时前
Agent 记忆出现重复和矛盾怎么优化:我实测了6种去重和更新策略,找到了低成本维护记忆质量的方法
算法
hans汉斯2 小时前
【计算机科学与应用】层级评论上下文依赖识别数据集构建与研究——以小红书旅游评论数据为例
人工智能·算法·yolo·目标检测·cnn·旅游
码行山野赴时序归途3 小时前
顺序表(Sequential List)详解:从数组到 C 语言实现
c语言·开发语言·数据结构·算法
Lokey8683 小时前
自注意力机制与多头注意力机制
算法
linx2953 小时前
单元七 · 零基础路线图-第 1–3 周·变量、类型与字符串
c语言·开发语言·数据结构·c++·算法