Minimum Cost to Make at Least One Valid Path in a Grid
Link
Description
Given an m x n
grid. Each cell of the grid has a sign pointing to the next cell you should visit if you are currently in this cell. The sign of grid[i][j]
can be:
1
which means go to the cell to the right. (i.e go from grid[i][j]
to grid[i][j + 1]
)
2
which means go to the cell to the left. (i.e go from grid[i][j]
to grid[i][j - 1]
)
3
which means go to the lower cell. (i.e go from grid[i][j]
to grid[i + 1][j]
)
4
which means go to the upper cell. (i.e go from grid[i][j]
to grid[i - 1][j]
)
Notice that there could be some signs on the cells of the grid that point outside the grid.
You will initially start at the upper left cell (0, 0)
. A valid path in the grid is a path that starts from the upper left cell (0, 0)
and ends at the bottom-right cell (m - 1, n - 1)
following the signs on the grid. The valid path does not have to be the shortest.
You can modify the sign on a cell with cost = 1
. You can modify the sign on a cell one time only.
Return the minimum cost to make the grid have at least one valid path.
Example 1:
- Input:
grid = [[1,1,1,1],[2,2,2,2],[1,1,1,1],[2,2,2,2]]
- Output:
3
- Explanation:
| You will start at point (0, 0).
The path to (3, 3) is as follows. (0, 0) --> (0, 1) --> (0, 2) --> (0, 3) change the arrow to down with cost = 1 --> (1, 3) --> (1, 2) --> (1, 1) --> (1, 0) change the arrow to down with cost = 1 --> (2, 0) --> (2, 1) --> (2, 2) --> (2, 3) change the arrow to down with cost = 1 --> (3, 3)
The total cost = 3.
|
Example 2:
- Input:
grid = [[1,1,3],[3,2,2],[1,1,4]]
- Output:
0
- Explanation:
You can follow the path from (0, 0) to (2, 2).
Example 3:
- Input:
grid = [[1,2],[4,3]]
- Output:
1
Constraints:
m == grid.length
n == grid[i].length
1 <= m, n <= 100
1 <= grid[i][j] <= 4
Solution
Dijkstra Algorithm
See reference (Chinese).
| using PII = pair<int, int>;
class Solution {
private:
static constexpr int dx[4] = {0, 0, 1, -1};
static constexpr int dy[4] = {1, -1, 0, 0};
public:
int minCost(vector<vector<int>>& grid) {
int m = grid.size(), n = grid[0].size();
vector<int> dist(m * n, 0x3f3f3f3f);
vector<bool> st(m * n, false);
priority_queue<PII, vector<PII>, greater<PII>> heap;
dist[0] = 0;
heap.emplace(0, 0);
while (!heap.empty()) {
auto [distance, vertex] = heap.top();
heap.pop();
if (st[vertex]) continue;
st[vertex] = true;
int x = vertex / n, y = vertex % n;
for (int i = 0; i < 4; i++) {
int newX = x + dx[i];
int newY = y + dy[i];
int newVertex = newX * n + newY;
int newDistance = distance + (grid[x][y] != i + 1);
if (newX >= 0 && newX < m && newY >= 0 && newY < n && newDistance < dist[newVertex]) {
dist[newVertex] = newDistance;
heap.emplace(newDistance, newVertex);
}
}
}
return dist[m * n - 1];
}
};
|
- Time complexity: \(O(MN\log (MN))\);
- Space complexity: \(O(MN)\).
0-1 BFS
| using PII = pair<int, int>;
class Solution {
private:
static constexpr int dx[4] = {0, 0, 1, -1};
static constexpr int dy[4] = {1, -1, 0, 0};
public:
int minCost(vector<vector<int>>& grid) {
int m = grid.size(), n = grid[0].size();
vector<int> dist(m * n, 0x3f3f3f3f);
vector<bool> st(m * n, false);
deque<int> q;
q.push_back(0);
dist[0] = 0;
while (!q.empty()) {
auto vertex = q.front();
q.pop_front();
if (st[vertex]) continue;
st[vertex] = true;
int x = vertex / n, y = vertex % n;
for (int i = 0; i < 4; i++) {
int newX = x + dx[i], newY = y + dy[i];
int newVertex = newX * n + newY;
int newDistance = dist[vertex] + (grid[x][y] != i + 1);
if (newX >= 0 && newX < m && newY >= 0 && newY < n && newDistance < dist[newVertex]) {
dist[newVertex] = newDistance;
if (grid[x][y] == i + 1)
q.push_front(newVertex);
else
q.push_back(newVertex);
}
}
}
return dist[m * n - 1];
}
};
|
- Time complexity: \(O(MN)\);
- Space complexity: \(O(MN)\).