https://leetcode.cn/problems/swim-in-rising-water/
Dijkstra
class Solution {
public:
int swimInWater(vector<vector<int>>& grid) {
vector<int> dirs{1,0,-1,0,1};
int m =grid.size(), n = grid[0].size();
priority_queue<tuple<int, int, int>, vector<tuple<int, int, int>>, greater<>> pq;
int dis[m][n];
memset(dis, 0x3f, sizeof(dis));
// dis[0][0] = 0;
pq.push({grid[0][0], 0, 0});
//答案一定存在
while (1) {
auto [d, x, y] = pq.top(); pq.pop();
// 到达终点
if (x == m - 1 && y == n - 1) return d;
// 四个方向寻找
for (int i = 0; i<4; i++) {
int a = x + dirs[i], b = y + dirs[i+1];
if (a >= 0 && a < m && b >= 0 && b < n) {
int nd = max(d, grid[a][b]);
// 更新最短路
if (nd < dis[a][b]) {
dis[a][b] = nd;
pq.push({nd, a, b});
}
}
}
}
}
};
class Solution {
public:
const int dir[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
int swimInWater(vector<vector<int>>& grid) {
int n = grid.size();
// 记录是否访问过
vector<vector<int>> seen(n, vector<int>(n, false));
// 格式: [值,坐标]
priority_queue<tuple<int, int, int>, vector<tuple<int, int, int>>, greater<> > pq;
pq.push({grid[0][0], 0, 0});
while (!pq.empty()) {
auto [val, x, y] = pq.top();pq.pop();
// 去重
if (seen[x][y]) continue;
seen[x][y] = true;
// 判断到达终点
if (x == n - 1 && y == n-1) return val;
// 访问相邻
for (int i = 0; i < 4; i++) {
int nx = x + dir[i][0], ny = y + dir[i][1];
if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;
pq.push({max(val, grid[nx][ny]), nx, ny});
}
}
return 0;
}
};
Binary Search + BFS
#define x first
#define y second
typedef pair<int, int> PII;
class Solution {
public:
bool vis[51][51];
int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1};
int h, w;
bool bfs(int xx, vector<vector<int>> & grid){
memset(vis, 0, sizeof vis);
queue<PII> q;
vis[0][0] = true;
q.push({0, 0});
while(q.size()){
auto t = q.front();
q.pop();
for(int i = 0; i < 4; i ++){
int a = t.x + dx[i], b = t.y + dy[i];
if(a >= 0 && a < h && b >= 0 && b < w && !vis[a][b] && grid[a][b] <= xx){
if(a == grid.size()-1 && b == grid[1].size()-1) return true;
q.push({a, b});
vis[a][b] = true;
}
}
}
return false;
}
int swimInWater(vector<vector<int>>& grid) {
h = grid.size();
w = grid[0].size();
if(h==1 && w==1) return 0; // 此处为能用dfs不要用bfs的原因 需要特殊处理 tx
int l = 0;
int r = h*w;
while(l < r){//二分
int mid = (l + r) >> 1;
if(grid[0][0] <= mid && bfs(mid, grid)) r = mid;
else l = mid + 1;
}
return l;
}
};
Binary Search + DFS
class Solution {
const int dirs[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
bool vis[50][50];
int n, m;
public:
int swimInWater(vector<vector<int>>& heights) {
m = heights.size();
n = heights[0].size();
int l = 0, r = n*n, m;
while(l < r){
m = (l + r) / 2;
memset(vis[0], 0, sizeof(vis));
if(heights[0][0] <= m && dfs(heights, 0, 0, m)){
r = m;
}
else{
l = m + 1;
}
}
return l;
}
int dfs(vector<vector<int> >& heights, int i, int j, int limit){
if(i==m-1&&j==n-1)return 1; // 通了
vis[i][j] = 1;
for(int t = 0; t < 4; t++){
int ii = i + dirs[t][0];
int jj = j + dirs[t][1];
if(ii<0||ii>=m||jj<0||jj>=n
|| vis[ii][jj] || heights[ii][jj] > limit) continue; // 限制边界/高
if(dfs(heights, ii, jj, limit))return 1;
}
return 0; // 没通
}
};
Union-Find
class Solution {
public:
const int dirs[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
vector<int> F;
int find(int x) {
return x == F[x] ? F[x] : F[x] = find(F[x]);
}
int swimInWater(vector<vector<int>>& grid) {
int N = grid.size();
F.resize(N * N);
iota(F.begin(), F.end(), 0);
using tiii = tuple<int, int, int>; // time x y
priority_queue<tiii, vector<tiii>, greater<> > nodes;
for (int i = 0; i < N; ++i) {
for (int j = 0; j < N; ++j) {
nodes.push({grid[i][j], i, j});
}
}
int t = 0;
while (1) {
auto [d, x, y] = nodes.top(); nodes.pop();
int z = x * N + y;
for (int i = 0; i < 4; ++i) {
int nx = x + dirs[i][0];
int ny = y + dirs[i][1];
int curParent = find(z);
//grid[nx][ny]< t // 把当前node周围比自己小的元素吃掉,用当前元素的parent
if (nx >= 0 && nx < N && ny >= 0 && ny < N && grid[nx][ny]< t) {
int nz = nx * N + ny;
F[find(nz)] = curParent ;
}
}
if (find(0) == find(N * N - 1)) {
return t;
}
t++;
}
}
};