碎碎念
a:我永远也忘不了2024.11.03,这个属于faker的日子
b:你也看英雄联盟吗?
a:不是啦,我说的是姜萍同学数学造假的事情
今天,阿里巴巴与涟水中专同时发布通报,确认姜萍同学确实存在作弊行为。 其实早该猜到是这样的结果了,毕竟今年的决赛成绩比往常的8月要晚了很久。
这起事件引发了广泛讨论,再次凸显了学术诚信的重要性。作弊行为不仅损害了个人的声誉,也影响了整个教育环境的公平性。希望未来能够加强监管,确保每位学生都能在公平的环境中竞争与成长。
对于这件事你有什么看法呢?
正文
今天的题目是力扣第 422 场周赛的第二道和第三道题目
3341. 到达最后一个房间的最少时间 I
问题描述
有一个地窖,地窖中有 n x m 个房间,它们呈网格状排布。
给你一个大小为 n x m 的二维数组 moveTime ,其中 moveTime[i][j] 表示在这个时刻 以后 你才可以 开始 往这个房间 移动 。你在时刻 t = 0 时从房间 (0, 0) 出发,每次可以移动到 相邻 的一个房间。在 相邻 房间之间移动需要的时间为 1 秒。
请你返回到达房间 (n - 1, m - 1) 所需要的 最少 时间。
如果两个房间有一条公共边(可以是水平的也可以是竖直的),那么我们称这两个房间是 相邻 的。
示例 1:
输入:moveTime = [[0, 4], [4, 4]]
输出:6
解释:
需要花费的最少时间为 6 秒。
在时刻 t == 4 ,从房间 (0, 0) 移动到房间 (1, 0) ,花费 1 秒。
在时刻 t == 5 ,从房间 (1, 0) 移动到房间 (1, 1) ,花费 1 秒。
示例 2:
输入:moveTime = [[0, 0, 0], [0, 0, 0]]
输出:3
解释:
需要花费的最少时间为 3 秒。
在时刻 t == 0 ,从房间 (0, 0) 移动到房间 (1, 0) ,花费 1 秒。
在时刻 t == 1 ,从房间 (1, 0) 移动到房间 (1, 1) ,花费 1 秒。
在时刻 t == 2 ,从房间 (1, 1) 移动到房间 (1, 2) ,花费 1 秒。
示例 3:
输入:moveTime = [[0, 1], [1, 2]]
输出:3
前置知识
本题目利用到了经典的 Dijkstra 算法
什么是 Dijkstra 算法?
Dijkstra 算法是一种用于计算从单个源节点到所有其他节点最短路径的算法。它适用于带权图,尤其是边权为非负值的情况。算法的基本思想是贪心策略:每次选择当前未处理节点中距离源节点最近的节点,并更新其邻居节点的距离。该算法通常使用优先队列来高效地获取下一个最短路径节点。
解题思路
问题理解
给定一个二维数组 moveTime,表示每个房间到达下一个房间所需的时间。目标是从起点 (0, 0) 到达终点 (n-1, m-1),并计算所需的最小时间。每次移动到相邻的房间时,所需时间取决于当前房间和目标房间之间的最大移动时间加上额外的移动时间。
Dijkstra 算法应用
使用 Dijkstra 算法来寻找最短路径。在这里,dist 数组用于记录从起点到每个房间的最小时间。初始化起点 (0, 0) 的距离为 0,其他房间初始化为无穷大 (Infinity)。
优先队列
使用优先队列(最小堆)来管理待处理节点,确保每次处理当前已知距离最小的节点。每次从队列中取出一个节点后,检查其相邻节点,并更新它们的最小距离。
状态更新
对于每个相邻房间,根据当前房间和目标房间之间的最大移动时间计算新的距离。如果新计算出的距离小于之前记录的距离,则更新该房间的距离,并将其加入优先队列。
终止条件
当处理到达终点 (n-1, m-1) 的节点时,返回当前已知的最小时间。
完整代码 JavaScript
/**
* @param {number[][]} moveTime
* @return {number}
*/
var minTimeToReach = function (moveTime) {
const n = moveTime.length;
const m = moveTime[0].length;
const dist = Array.from({ length: n }, () => Array(m).fill(Infinity));
const directions = [
[0, -1],
[0, 1],
[-1, 0],
[1, 0],
];
const pq = new MinPriorityQueue({ priority: (item) => item[0] });
dist[0][0] = 0;
pq.enqueue([dist[0][0], 0, 0]);
while (!pq.isEmpty()) {
const [d, i, j] = pq.dequeue().element;
if (i === n - 1 && j === m - 1) {
return d;
}
if (d > dist[i][j]) {
continue;
}
for (const [dx, dy] of directions) {
const x = i + dx;
const y = j + dy;
if (x < 0 || x >= n || y < 0 || y >= m) continue;
const cur = moveTime[x][y];
const nxt = Math.max(d, cur) + ((i + j) % 2) + 1;
if (nxt < dist[x][y]) {
dist[x][y] = nxt;
pq.enqueue([dist[x][y], x, y]);
}
}
}
};
3342. 到达最后一个房间的最少时间 II
问题描述
有一个地窖,地窖中有
n x m个房间,它们呈网格状排布。给你一个大小为
n x m的二维数组moveTime,其中moveTime[i][j]表示在这个时刻以后你才可以开始往这个房间移动。你在时刻t = 0时从房间(0, 0)出发,每次可以移动到相邻的一个房间。在相邻房间之间移动需要的时间为:第一次花费 1 秒,第二次花费 2 秒,第三次花费 1 秒,第四次花费 2 秒……如此往复。请你返回到达房间
(n - 1, m - 1)所需要的最少时间。如果两个房间有一条公共边(可以是水平的也可以是竖直的),那么我们称这两个房间是相邻的。
示例
示例 1:
输入:moveTime = [[0, 4], [4, 4]]
输出:7
解释:
需要花费的最少时间为 7 秒。
在时刻 t == 4 ,从房间 (0, 0) 移动到房间 (1, 0) ,花费 1 秒。
在时刻 t == 5 ,从房间 (1, 0) 移动到房间 (1, 1) ,花费 2 秒。
示例 2:
输入:moveTime = [[0, 0, 0, 0], [0, 0, 0, 0]]
输出:6
解释:
需要花费的最少时间为 6 秒。
在时刻 t == 0 ,从房间 (0, 0) 移动到房间 (1, 0) ,花费 1 秒。
在时刻 t == 1 ,从房间 (1, 0) 移动到房间 (1, 1) ,花费 2 秒。
在时刻 t == 3 ,从房间 (1, 1) 移动到房间 (1, 2) ,花费 1 秒。
在时刻 t == 4 ,从房间 (1, 2) 移动到房间 (1, 3) ,花费 2 秒。
示例 3:
输入:moveTime = [[0, 1], [1, 2]]
输出:4
解题思路
本题与上一题的思路大致相同,但需要根据当前格子的奇偶性来判断每次移动所需的时间。具体来说:
- 奇偶性判断:在移动过程中,根据当前所在格子的行和列之和的奇偶性来决定移动所需的时间。如果当前格子的行列之和为偶数,则移动耗时为
1秒;如果为奇数,则耗时为2秒。这种交替的耗时模式需要在计算新距离时考虑进去。 - 使用 Dijkstra 算法:我们将使用 Dijkstra 算法来寻找从起点到终点的最短路径。初始化一个距离数组
dist,用于记录从起点到每个房间的最小时间。 - 优先队列管理节点:使用优先队列(最小堆)来管理待处理节点,以确保每次处理当前已知距离最小的节点。
由于使用数组会超时,需要使用力扣内置的包来使用队列实现
完整代码 JavaScript
/**
* @param {number[][]} moveTime
* @return {number}
*/
var minTimeToReach = function (moveTime) {
const n = moveTime.length;
const m = moveTime[0].length;
const directions = [
[0, -1],
[0, 1],
[-1, 0],
[1, 0],
];
const dist = Array.from({ length: n }, () => new Array(m).fill(Infinity));
dist[0][0] = 0;
const qe = new MinPriorityQueue({ priority: (item) => item[0] });
qe.enqueue([0, 0, 0]);
while (!qe.isEmpty()) {
const [d, i, j] = qe.dequeue().element;
if (i === n - 1 && j === m - 1) {
return d;
}
if (d > dist[i][j]) {
continue;
}
for (const [dx, dy] of directions) {
const x = i + dx;
const y = j + dy;
if (x < 0 || x >= n || y < 0 || y >= m) {
continue;
}
const nxt = Math.max(d, moveTime[x][y]) + ((i + j) % 2) + 1;
if (nxt < dist[x][y]) {
dist[x][y] = nxt;
qe.enqueue([nxt, x, y]);
}
}
}
};
本文使用 mdnice 排版