Lintcode 1543 · Unique Path IV (DP 好题)

1543 · Unique Path IV
Algorithms
Description
Solution14
Notes
Discuss26
Leaderboard
Record

Description
Give two integers to represent the height and width of the grid. The starting point is in the upper left corner and the ending point is in the upper right corner. You can go to the upper right corner, right or lower right corner. Find out the number of paths you can reach the end. And the result needs to mod 1000000007.

width > 1, height > 1

Example
Example 1:

Input:
height = 3
width = 3
Output:
2
Explanation: There are two ways from start to end.

image

Example 2:

Input:
height = 2
weight = 2
Output:
1
Explanation: There are only one way from (1,1) to (2,1)

解法1:
反过来逆推,从右上角开始,那么行要从上到下,列要从右到左。
注意:很重要的一点是列要放在外循环
以5行4列矩阵为例,a[0][4]为终点,dp[0][4]=1。那么其相邻的dp[0][3]=1, dp[1,3]=1,dp[1][4]=0。
如果行循环在外面,那么列会先更新,dp[0][3]=1,dp[0][2]=1,…。我们可以看到dp[0][3]先于dp[1][4]更新,但实际上dp[0][3]应该后于dp[1][4]。

class Solution {
public:
    /**
     * @param height: the given height
     * @param width: the given width
     * @return: the number of paths you can reach the end
     */
    int uniquePath(int height, int width) {
        #define MOD 1000000007
        if (height == 0 || width == 0) return 1;
        vector<vector<int>> dp(height, vector<int>(width, 0));
        dp[0][width - 1] = 1;
        for (int j = width - 1; j >= 0; j--) {   //注意列在先。因为
            for (int i = 0; i < height; i++) {
                if (j - 1 >= 0) {
                    if (i + 1 < height) {
                        dp[i + 1][j - 1] = (dp[i + 1][j - 1] + (dp[i][j] % MOD)) % MOD;
                    }
                    dp[i][j - 1] = (dp[i][j - 1] + (dp[i][j] % MOD)) % MOD;
                    if (i - 1 >= 0) {
                        dp[i - 1][j - 1] = (dp[i - 1][j - 1] + (dp[i][j] % MOD)) % MOD;
                    }

                }
            }
        }
        return dp[0][0] % MOD;
    }
};

解法2:正向推。注意:很重要的一点也是列要放在外循环

class Solution {
public:
    /**
     * @param height: the given height
     * @param width: the given width
     * @return: the number of paths you can reach the end
     */
    int uniquePath(int height, int width) {
        #define MOD 1000000007
        if (height == 0 || width == 0) return 1;
        vector<vector<int>> dp(height, vector<int>(width, 0));
        dp[0][0] = 1;
        for (int j = 0; j < width; j++) {
            for (int i = 0; i < height; i++) {
                if (j - 1 >= 0) {
                    dp[i][j] = (dp[i][j] + dp[i][j - 1]) % MOD;
                    if (i - 1 >= 0) {
                        dp[i][j] = (dp[i][j] + dp[i - 1][j - 1]) % MOD;
                    }
                    if (i + 1 < height) {
                        dp[i][j] = (dp[i][j] + dp[i + 1][j - 1]) % MOD;
                    }
                }
            }
        }
        return dp[0][width - 1];
    }
};

上面的if (j-1>=0)可以简化

class Solution {
public:
    /**
     * @param height: the given height
     * @param width: the given width
     * @return: the number of paths you can reach the end
     */
    int uniquePath(int height, int width) {
        #define MOD 1000000007
        if (height == 0 || width == 0) return 1;
        vector<vector<int>> dp(height, vector<int>(width, 0));
        dp[0][0] = 1;
        for (int j = 1; j < width; j++) {
            for (int i = 0; i < height; i++) {
                dp[i][j] = (dp[i][j] + dp[i][(j - 1)]) % MOD; //也可以直接写成dp[i][j] = dp[i][(j - 1)] % MOD;
                if (i - 1 >= 0) {
                    dp[i][j] = (dp[i][j] + dp[i - 1][(j - 1)]) % MOD;
                }
                if (i + 1 < height) {
                    dp[i][j] = (dp[i][j] + dp[i + 1][(j - 1)]) % MOD;
                }
            }
        }
        return dp[0][(width - 1)];
    }
};

加上滚动数组优化:

class Solution {
public:
    /**
     * @param height: the given height
     * @param width: the given width
     * @return: the number of paths you can reach the end
     */
    int uniquePath(int height, int width) {
        #define MOD 1000000007
        if (height == 0 || width == 0) return 1;
        vector<vector<int>> dp(height, vector<int>(2, 0));
        dp[0][0] = 1;
        for (int j = 1; j < width; j++) {
            for (int i = 0; i < height; i++) {
                dp[i][j % 2] = dp[i][(j - 1) % 2] % MOD;   //注意这里不能用 dp[i][j%2] = (dp[i][j%2] + dp[i][(j - 1)%2]) % MOD; 因为dp[i][j%2]会跟之前的值混淆。如果不用滚动数组可以
                if (i - 1 >= 0) {
                    dp[i][j % 2] = (dp[i][j % 2] + dp[i - 1][(j - 1) % 2]) % MOD;
                }
                if (i + 1 < height) {
                    dp[i][j % 2] = (dp[i][j % 2] + dp[i + 1][(j - 1) % 2]) % MOD;
                }
            }
        }
        return dp[0][(width - 1) % 2];
    }
};

你可能感兴趣的:(算法,leetcode,数据结构)