LintCode解题记录 动态规划专题 Part1 17.11.4

写在前面

最近这一周多吧,都在做动态规划的题目。把一些经典的动态规划题目基础夯实(比如各大教材中关于动态规划章节所讲的例子),然后对每一道动态规划的题目,都要仔细思考 这个递归关系是怎么得来的,这样的话动态规划的功力才会得到进步。

Minimum Path Sum

题目描述

给定一个mxn的非负整数矩阵,问你求得一条从左上到右下的路径,使得这条路径上的数字和最小,每次只能往下走一格或者往右走一格。返回这个最小值。

思路

这道题的动态规划思路还是很明显的。我们定义一个dp[i][j]表示到达点(i, j)的最短路径。显然,该状态可由两个子状态推导得到,(i-1, j)往右走一格或者(i, j-1)往下走一格,所以递归关系:

dp[i][j] = min{dp[i-1][j], dp[i][j-1]} + grid[i][j];
边界条件
dp[0][0] = grid[0][0];
dp[0][j] = dp[0][j-1] + grid[0][j], 0 < j < n;
dp[i][0] = dp[i-1][0] + grid[i][0], 0 < i < m;
代码
    int minPathSum(vector<vector<int>> &grid) {
        // write your code here
        if (grid.size() == 0 || grid[0].size() == 0) return 0;
        int m = grid.size(), n = grid[0].size();
        vector<vector<int>> dp(m, vector<int>(n, 0));
        dp[0][0] = grid[0][0];
        for (int i = 1; i < m; i++) dp[i][0] = dp[i-1][0] + grid[i][0];
        for (int j = 1; j < n; j++) dp[0][j] = dp[0][j-1] + grid[0][j];

        for (int i = 1; i < m; i++) {
            for (int j = 1; j < n; j++) {
                dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + grid[i][j];
            }
        }
        return dp[m-1][n-1];
    }

Paint Fence

题目描述

假设有n个点,每一个点都有k种颜色可以涂。你现在要给所有的点涂色,但是要求不能有超过两个的邻近的点拥有相同的颜色。请问这样的涂色方式一共有多少种。

思路

这道题的英语真是捉急了,后面的那句”such that no more than two adjacent fence posts have the same color”愣是没怎么读懂。直到看了别人的答案才明白原来是这个要求。就是说,连续相同的颜色不能超过两个。即”000”就不符合题意,但是”0011”就符合题意。
我们发现对于第i个点来说,如果要求其颜色和前面一个点不一样,那么就有k-1种途法,如果和前面的点一样,那么就首先得要求前面的点不能和前前一个点颜色相同,否则就不符合题意。因此,对第i个点,我们用dp[i][0]表示第i个点和前面一点颜色不同的涂法,而用dp[i][1]表示第i个点和前面一点颜色相同的途法。这样,得到如下递归关系:

dp[i][0] = (dp[i-1][0]+dp[i-1][1]) * (k-1);
dp[i][1] = dp[i-1][0];
//机智的小伙伴肯定发现了可以用两个变量来代替dp,即diff = dp[i-1][0], same = diff[i-1][1],那么上述递推关系就变为:
int tmp = diff;
diff = (same + diff)*(k-1);
same = tmp;
边界条件:第一个点same = 0, diff = k.
代码
    int numWays(int n, int k) {
        // write your code here
        if (n == 1) return k;
        int same = 0, diff = k;
        for (int i = 2; i <= n; i++) {
            int t = diff;
            diff = (same+diff)*(k-1);
            same = t;
        }
        return same+diff;
    }
总结

有的时候先用复杂的递归公式将问题刻画出来,然后再考虑如何优化空间复杂度。

Cutting a Rod

题目描述

有一根长为n的绳子,然后同时给定了长度为i的绳子可以卖j元。那么问题如何割这根绳子,

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值