题目描述
给你一个 R 行 C 列的整数矩阵 A。矩阵上的路径从 [0,0] 开始,在 [R-1,C-1] 结束。
路径沿四个基本方向(上、下、左、右)展开,从一个已访问单元格移动到任一相邻的未访问单元格。
路径的得分是该路径上的 最小 值。例如,路径 8 → 4 → 5 → 9 的值为 4 。
找出所有路径中得分 最高 的那条路径,返回其 得分。
示例 1:
输入:[[5,4,5],[1,2,6],[7,4,6]]
输出:4
解释:
得分最高的路径用黄色突出显示。示例 2:
输入:[[2,2,1,2,2,2],[1,2,2,2,1,2]]
输出:2示例 3:
输入:[[3,4,6,3,4],[0,2,1,1,7],[8,8,3,2,7],[3,2,4,9,8],[4,1,2,0,0],[4,6,5,4,3]]
输出:3提示:
1 <= R, C <= 100
0 <= A[i][j] <= 10^9
算法分析
DFS + 二分搜索:
用二分法逼近答案。
1、假设初始位置和结束位置中的最小值,为目前已知的所有满足最小最大的路径中的最大值。(每条满足条件的路径必须经过起始位置和结束位置),我们要做的就是寻找还有没有比满足最小最大条件的比这个值还小的值。从而做到了剪枝操作,用深度优先搜索寻找一条路径的最小值是mid的路径,看有没有这个路径。
2、每次选择一个值mid,0<= mid <=min(start,end)
dfs里面有一条路径每个值都大于等于这个值mid,说明当前A可用,然后继续增大mid,否则减少mid,直到二分退出,此时mid就是答案。
dfs+二分搜索
class Solution {
public:
vector<int> dict{-1,0,1,0,-1};
int R,C;
bool inArea(int x, int y) {
return x >= 0 && x < R && y >= 0 && y < C;
}
bool dfs(vector<vector<int>>& grid,vector<vector<bool>>& visited, int row, int col, int& mid) {
if(!inArea(row,col) || grid[row][col] < mid || visited[row][col]) {
return false;
}
if(row == R-1 && col == C-1) {
return true;
}
visited[row][col] = true;
for(int i = 0; i < 4; ++i) {
int new_row = row + dict[i];
int new_col = col + dict[i+1];
if(dfs(grid, visited, new_row, new_col, mid)) {
return true;
}
}
// visited[row][col] = false; //回溯超时
return false;
}
int maximumMinimumPath(vector<vector<int>>& grid) {
R = grid.size();
C = grid[0].size();
int left = 0;
int right = min(grid[0][0], grid[R-1][C-1]);
int ans = 0;
while(left <= right) {
vector<vector<bool>> visited(R, vector<bool>(C, false));
int mid = left +(right-left)/2;
if(dfs(grid,visited,0,0,mid)) {
left = mid + 1;
ans = mid;
} else {
right = mid - 1;
}
}
return ans;
}
};
BFS+优先级队列
class Solution {
public:
int maximumMinimumPath(vector<vector<int>>& grid) {
int R = grid.size();
int C = grid[0].size();
vector<int> dict{-1,0,1,0,-1};
vector<vector<bool>> visited(R, vector<bool>(C, false));
priority_queue<point> que;
int res = min(grid[0][0], grid[R-1][C-1]);
que.push(point(0,0,grid[0][0]));
// visited[0][0] = true;
while(!que.empty()) {
auto cur = que.top();
que.pop();
int x = cur.x;
int y = cur.y;
if(visited[x][y]) {
continue;
}
visited[x][y] = true;
res = min(res, grid[x][y]);
if(x == R-1 && y == C-1) {
return res;
}
for(int i =0; i < 4; ++i) {
int new_x = x + dict[i];
int new_y = y + dict[i+1];
if(new_x < 0 || new_x >= R || new_y < 0 || new_y >= C || visited[new_x][new_y]) {
continue;
}
que.push(point(new_x, new_y, grid[new_x][new_y]));
}
}
return res;
}
private:
struct point {
int x;
int y;
int val;
point(int x_, int y_, int val_) {
this->x = x_;
this->y = y_;
this->val = val_;
}
bool operator < (const point& other) const {
return this->val < other.val;
}
};
};