[LeetCode] Out of Boundary Paths 出界的路徑


 

There is an m by n grid with a ball. Given the start coordinate (i,j) of the ball, you can move the ball to adjacent cell or cross the grid boundary in four directions (up, down, left, right). However, you can at most move N times. Find out the number of paths to move the ball out of grid boundary. The answer may be very large, return it after mod 109 + 7.

Example 1:

Input:m = 2, n = 2, N = 2, i = 0, j = 0
Output: 6
Explanation:

 

Example 2:

Input:m = 1, n = 3, N = 3, i = 0, j = 1
Output: 12
Explanation:

 

Note:

  1. Once you move the ball out of boundary, you cannot move it back.
  2. The length and height of the grid is in range [1,50].
  3. N is in range [0,50].

 

這道題給了我們一個二維的數組,某個位置放個足球,每次可以在上下左右四個方向中任意移動一步,總共可以移動N步,問我們總共能有多少種移動方法能把足球移除邊界,由於結果可能是個巨大的數,所以讓我們對一個大數取余。那么我們知道對於這種結果很大的數如果用遞歸解法很容易爆棧,所以最好考慮使用DP來解。那么我們使用一個三維的DP數組,其中dp[k][i][j]表示總共走k步,從(i,j)位置走出邊界的總路徑數。那么我們來找遞推式,對於dp[k][i][j],走k步出邊界的總路徑數等於其周圍四個位置的走k-1步出邊界的總路徑數之和,如果周圍某個位置已經出邊界了,那么就直接加上1,否則就在dp數組中找出該值,這樣整個更新下來,我們就能得出每一個位置走任意步數的出界路徑數了,最后只要返回dp[N][i][j]就是所求結果了,參見代碼如下:

 

解法一:

class Solution {
public:
    int findPaths(int m, int n, int N, int i, int j) {
        vector<vector<vector<int>>> dp(N + 1, vector<vector<int>>(m, vector<int>(n, 0)));
        for (int k = 1; k <= N; ++k) {
            for (int x = 0; x < m; ++x) {
                for (int y = 0; y < n; ++y) {
                    long long v1 = (x == 0) ? 1 : dp[k - 1][x - 1][y];
                    long long v2 = (x == m - 1) ? 1 : dp[k - 1][x + 1][y];
                    long long v3 = (y == 0) ? 1 : dp[k - 1][x][y - 1];
                    long long v4 = (y == n - 1) ? 1 : dp[k - 1][x][y + 1];
                    dp[k][x][y] = (v1 + v2 + v3 + v4) % 1000000007;
                }
            }
        } 
        return dp[N][i][j];
    }
};

 

下面這種方法雖然也是用的DP解法,但是DP數組的定義和上面的不一樣,這種解法相當於使用了BFS搜索,以(i, j)為起始點,其中dp[k][x][y]表示用了k步,進入(x, y)位置的路徑數,由於dp[k][x][y]只依賴於dp[k-1][x][y],所以我們可以用一個二維dp數組來代替,初始化dp[i][j]為1,總共N步,進行N次循環,每次都新建一個mxn大小的臨時數組t,然后就是對於遍歷到的每個位置,都遍歷其四個相鄰位置,如果相鄰位置越界了,那么我們用當前位置的dp值更新結果res,因為此時dp值的意義就是從(i,j)到越界位置的路徑數。如果沒有,我們將當前位置的dp值賦給t數組的對應位置,這樣在遍歷完所有的位置時,將數組t整個賦值給dp,然后進入下一步的循環,參加代碼如下:

 

解法二:

class Solution {
public:
    int findPaths(int m, int n, int N, int i, int j) {
        int res = 0;
        vector<vector<int>> dp(m, vector<int>(n, 0));
        dp[i][j] = 1;
        vector<vector<int>> dirs{{0,-1},{-1,0},{0,1},{1,0}};
        for (int k = 0; k < N; ++k) {
            vector<vector<int>> t(m, vector<int>(n, 0));
            for (int r = 0; r < m; ++r) {
                for (int c = 0; c < n; ++c) {
                    for (auto dir : dirs) {
                        int x = r + dir[0], y = c + dir[1];
                        if (x < 0 || x >= m || y < 0 || y >= n) {
                            res = (res + dp[r][c]) % 1000000007;
                        } else {
                            t[x][y] = (t[x][y] + dp[r][c]) % 1000000007;
                        }
                    }
                }
            }
            dp = t;
        } 
        return res;
    }
};

 

參考資料:

https://discuss.leetcode.com/topic/88492/c-6-lines-dp-o-n-m-n-6-ms

https://discuss.leetcode.com/topic/88570/java-solution-dp-with-space-compression

 

LeetCode All in One 題目講解匯總(持續更新中...)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM