778. Swim in Rising Water

On an N x N grid, each square grid[i][j] represents the elevation at that point (i,j).

Now rain starts to fall. At time t, the depth of the water everywhere is t. You can swim from a square to another 4-directionally adjacent square if and only if the elevation of both squares individually are at most t. You can swim infinite distance in zero time. Of course, you must stay within the boundaries of the grid during your swim.

You start at the top left square (0, 0). What is the least time until you can reach the bottom right square (N-1, N-1)?

Example 1:

Input: [[0,2],[1,3]]
Output: 3
Explanation:
At time 0, you are in grid location (0, 0).
You cannot go anywhere else because 4-directionally adjacent neighbors have a higher elevation than t = 0.

You cannot reach point (1, 1) until time 3.
When the depth of water is 3, we can swim anywhere inside the grid.
Example 2:

Input: [[0,1,2,3,4],[24,23,22,21,5],[12,13,14,15,16],[11,17,18,19,20],[10,9,8,7,6]]
Output: 16
Explanation:
 0  1  2  3  4
24 23 22 21  5
12 13 14 15 16
11 17 18 19 20
10  9  8  7  6

The final route is marked in bold.
We need to wait until time 16 so that (0, 0) and (4, 4) are connected.
Note:

2 <= N <= 50.
grid[i][j] is a permutation of [0, ..., N*N - 1].

解题思路

  • 1)因为可以多个方向,马上想到了动规和BFS,如果使用动规, 最终求dp[n][m], 它只依赖dp[n - 1][m] 和 dp[n][m - 1], 看起来可以,但是发现这两个点也依赖dp[n][m], 相互依赖的关系,我搞不清楚,感觉这样不能做,所以放弃了DP的想法.
  • 2)转到BFS, BFS通常的套路是,把所有可能的情况入队,然后依次出队,看下出队的值是否满足解. 所以想按这个套路来。终止条件肯定是x = n, y = m, 但如果是单纯的遍历,push进去,再pop, 那只相当于遍历了这个grid,对解题没有任何帮助。注意到t是递增的值,
    只有grid[i][j] >= t的时候,i,j这个点才可以向四个方向扩散,所以感觉是一个带权重的BFS扩散. 常规的BFS,四个方向权重一样,没有先后次序,但这道题相当于值小的可以先扩散, 只要保证从0,0开始,每次从当前值最小的点开始扩散,先扩散到m,n的,肯定是最少的. 所以数据结构使用了优先队列,值最小的放在队列头部. 需要注意的是,如果i,j 大于周围的某个点时,该点的值要更新成grid[i][j]. 因为i,j点是当前从0,0出发后,所能到达的最小点, 所以该点也需要和i,j相同的步数才可以到达.

CPP实现

struct Node {
    public:
        int val;
        int x;
        int y;
    public:
        Node(int val, int x, int y) {
            this->val = val;
            this->x = x;
            this->y = y;
        }
        ~Node() {}
    
        bool operator < (const Node& node) const {
            return val > node.val;
        }
};

class Solution {
public:
    //bfs
    int swimInWater(vector<vector<int>>& grid) {
        int n = grid.size();
        int m = grid[0].size();
        vector<vector<int>> visited(n, vector<int>(m, 0));
        priority_queue<Node> q;
        int dx[4] = {1, -1, 0, 0};
        int dy[4] = {0, 0, 1, -1};
        Node node(grid[0][0], 0, 0);
        q.push(node);
        visited[0][0] = 1;
        while(!q.empty()) {
            Node cur = q.top();
            q.pop();
            if(cur.x == n - 1 && cur.y == m - 1) return cur.val;
            for(int k = 0; k < 4; k++) {
                int nx = cur.x + dx[k];
                int ny = cur.y + dy[k];
                if(isInGrid(nx, ny, n, m) && visited[nx][ny] == 0 ) {
                    grid[nx][ny] = max(grid[cur.x][cur.y], grid[nx][ny]);
                    q.push(Node(grid[nx][ny], nx, ny));
                    visited[nx][ny] = 1;
                }
            }
        }
    }
    
    bool isInGrid(int x, int y, int n, int m) {
        if(x >= 0 && x < n && y >= 0 && y < m) return true;
        return false;
    }
};

JAVA实现

class Node {
    public int val;
    public int x;
    public int y;
    Node(int val, int x, int y) {
        this.val = val;
        this.x = x;
        this.y = y;
    }
}

public class Solution {
    //bfs
    public int swimInWater(int[][] grid) {
        int n = grid.length;
        int m = grid[0].length;
        int[][] visited = new int[n][m];
        Comparator<Node> cmp = new Comparator<Node>() {
            public int compare(Node a, Node b) {
                return a.val - b.val;
            }
        };
        int[] dx = {1, -1, 0, 0};
        int[] dy = {0, 0, -1, 1};
        PriorityQueue<Node> q = new PriorityQueue<Node>(n * m, cmp);
        Node node = new Node(grid[0][0], 0, 0);
        q.offer(node);
        visited[0][0] = 1;
        while(!q.isEmpty()) {
            Node cur = q.poll();
            if(cur.x == n - 1 && cur.y == m - 1) {
                return cur.val;
            }
            
            for(int k = 0; k < 4; k++) {
                int nx = cur.x + dx[k];
                int ny = cur.y + dy[k];
                if(isInGrid(nx, ny, n, m) && visited[nx][ny] == 0) {
                    grid[nx][ny] = Math.max(grid[cur.x][cur.y], grid[nx][ny]);
                    q.offer(new Node(grid[nx][ny], nx, ny));
                    visited[nx][ny] = 1;
                }
            }
        }
        
        return 0;
    }
    
    public boolean isInGrid(int x, int y, int n, int m) {
        if(x >= 0 && x < n && y >= 0 && y < m) return true;
        return false;
    }
}
posted @ 2018-02-05 20:26  JinleiZhang  阅读(524)  评论(0编辑  收藏  举报