1631. Path With Minimum Effort (dijkstra
Last updated
Last updated
้้กๆไธ็ดๅธถ่ effort from start to end
ๆไปฅไธญ้่ฆๆดๆฐๆ, ่ฆๆๅคง็(origin effort and new effort)
ไฝๆๅบ pq ๆ, ่ฆๆๅฐ็, ้ๆจฃๆๅพๆๆๆฏ min effort
time: O(m*n * log(m*n))
space: O(m*n) // efftor matrix
use Dijkstra's algo
class Solution {
public int minimumEffortPath(int[][] heights) {
int m = heights.length;
int n = heights[0].length;
int effort[][] = new int[m][n];
for (int i = 0; i < m ; i++) {
Arrays.fill(effort[i], Integer.MAX_VALUE);
}
PriorityQueue<int[]> pq = new PriorityQueue<>(Comparator.comparingInt(a -> a[0]));
pq.offer(new int[]{0, 0, 0});
while (!pq.isEmpty()) {
int min[] = pq.poll();
int dist = min[0];
int row = min[1];
int col = min[2];
if (dist > effort[row][col]) { // prunig
continue;
}
if (row == m - 1 && col == n - 1) {
return dist;
}
int dir[][] = new int[][]{{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
for (int d[] : dir) {
int newRow = row + d[0];
int newCol = col + d[1];
if (newRow >= 0 && newRow < m && newCol >= 0 && newCol < n) {
// notie here
int newDist = Math.max(dist, Math.abs(heights[newRow][newCol] - heights[row][col]));
if (newDist < effort[newRow][newCol]) {
effort[newRow][newCol] = newDist;
pq.offer(new int[]{newDist, newRow, newCol});
}
}
}
}
return 0;
}
}
class Solution {
private static final int[][] DIRS = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
class State {
int x;
int y;
int dist;
State(int x, int y, int dist) {
this.x = x;
this.y = y;
this.dist = dist;
}
}
public int minimumEffortPath(int[][] heights) {
int m = heights.length;
int n = heights[0].length;
Queue<State> pq = new PriorityQueue<>((a, b) -> a.dist - b.dist);
pq.offer(new State(0, 0, 0));
int[][] visited = new int[m][n];
for (int i = 0; i < m; i++) {
Arrays.fill(visited[i], Integer.MAX_VALUE);
}
while (!pq.isEmpty()) {
State cur = pq.poll();
int x = cur.x;
int y = cur.y;
int dist = cur.dist;
if (dist > visited[x][y]) {
continue;
}
if (x == m-1 && y == n-1) {
return dist;
}
for (int[] dir : DIRS) {
int newX = x + dir[0];
int newY = y + dir[1];
if (!isValid(heights, newX, newY)) {
continue;
}
// max (dist, diff)
int newDist = Math.max(dist, Math.abs(heights[x][y] - heights[newX][newY]));
if (newDist < visited[newX][newY]) {
visited[newX][newY] = newDist;
pq.offer(new State(newX, newY, newDist));
}
}
}
return 0;
}
private boolean isValid(int[][] heights, int x, int y) {
int m = heights.length;
int n = heights[0].length;
return x >= 0 && x < m && y >= 0 && y < n;
}
}
/*
A route's effort is the maximum absolute difference in heights between two consecutive cells of the route.
so effort is cell to cell's diff (maximum absolute difference)
cal the smallest effort
minimum effort required to travel from the top-left cell to the bottom-right cell.
so start: (0, 0)
end : (m-1, n-1)
effort: abs(cur x, y - next x, y)
pq: (x, y, effort)
update dist = min(dist, effor)
(0, 0, 0)
[x][y] = 1
(0, 1, 1) => choose this, dist = 1
if (newDist < effor[][]) {
efforp[][] = newDist;
}
(1, 0, 2)
*/
```java
class Solution {
private static final int[][] DIRECTIONS = {{0,1}, {1, 0}, {0, -1}, {-1, 0}};
class State {
int x;
int y;
int effort;
State(int x, int y, int effort) {
this.x = x;
this.y = y;
this.effort = effort;
}
}
public int minimumEffortPath(int[][] heights) {
int m = heights.length;
int n = heights[0].length;
int[][] effortTo = new int[m][n];
for (int i = 0; i < m; i++) {
Arrays.fill(effortTo[i], Integer.MAX_VALUE);
}
effortTo[0][0] = 0; // mark start effor = 0
Queue<State> pq = new PriorityQueue<>((a, b) -> a.effort - b.effort);
pq.offer(new State(0, 0, 0));
while (!pq.isEmpty()) {
State currState = pq.poll();
if (currState.x == m-1 && currState.y == n-1) {
return currState.effort;
}
for (int[] dir : DIRECTIONS) {
int nextX = currState.x + dir[0];
int nextY = currState.y + dir[1];
if (nextX >= 0 && nextX < m && nextY >= 0 && nextY < n) {
int newEffort = Math.max(
currState.effort,
Math.abs(heights[nextX][nextY] - heights[currState.x][currState.y])
);
if (effortTo[nextX][nextY] > newEffort) {
effortTo[nextX][nextY] = newEffort;
pq.offer(new State(nextX, nextY, newEffort));
}
}
}
}
return -1;
}
}
/*
effort, if new curr to next effort < existing effort in nodes
use Dikstra to maintain ""min effort in the path""
-> keep going, add to queue
A route's effort is the maximum ""absolute"" difference in heights between two consecutive cells of the route.
*/
```