动态规划公共子问题模式总结

动态规划公共子问题模式

在解决动态规划问题时候, 关键的一点就是找到子问题, 在动态规划中有一些常见的子问题模式,需要熟悉。下面就是一些常见子问题模式总结


1. 输入为x1,x2,···, xn输出为x1,x2, ···, xi

在这里插入图片描述

在这种情况下,子问题是从x1~xi这一部分。
子问题的个数一般为n, 所以用一个dp[n]的数组就能把子问题的解保存

例子:LeetCode746 Min Cost Climbing Stairs(爬上楼梯的最小损失)

博客地址:
https://blog.csdn.net/qq874455953/article/details/82564279

此题利用的就是求当前的dp[i], 要用到前面的dp[i-1]和dp[i-2]. 也就是说子问题是由前面的x1~xi-1得到的。

class Solution {
public:
    int minCostClimbingStairs(vector<int>& cost) {
        //定义一个数组 表示爬上每一层楼梯 需要的最少cost
        vector<int> dp(cost.size(), 0);
        //第一层楼梯和第二层楼梯的cost就是本身
        dp[0] = cost[0];
        dp[1] = cost[1];
        //现在循环计算 后面每一层的最小cost

        for (int i = 2; i < cost.size(); i++) {
            dp[i] = min(dp[i-2] + cost[i], dp[i-1] + cost[i]);
        }

        //到达楼梯终点的最小cost 就是倒数第一层和第二层的最小cost值
        return min(dp[cost.size()-2] , dp[cost.size()-1]);
    }
};

2. 输入为x1,x2,···, xn和y1,y2,···, yn, 输出为x1,x2, ···, xi和y1,y2,···, yi

在这里插入图片描述

在这种情况下, 子问题个数一般为m * n, 所以用dp[m][n] 就能把子问题的解保存

例子:编辑距离

博客地址
https://blog.csdn.net/qq_36124194/article/details/83716115

输入为两个字符串, 也就是x1 ··· xm , y1 ··· yn ,解的结果是在两个字符串前面的子字符串产生。

class Solution {
public:
    int minDistance(string word1, string word2) {
        int size1 = word1.size();
        int size2 = word2.size();
        vector<vector<int>> count(size1+1, vector<int>(size2+1, 0));
        for(int i = 0; i <= size1; i++) {
        	count[i][0] = i;
        }
        for(int i = 0; i <= size2; i++) {
        	count[0][i] = i;
        }

        for(int i = 1; i <= size1; i++) {
        	for(int j = 1; j <= size2; j++) {
        		int tag = 0;
        		if(word1[i-1] != word2[j-1]) {
        			tag = 1;
        		}
        		count[i][j] = min(count[i-1][j]+1, count[i][j-1]+1);
        		count[i][j] = min(count[i][j], tag+count[i-1][j-1]);
        	}
        }
        return count[size1][size2];
    }
};

3. 输入为x1,x2,···, xn, 输出为xi,xi+1,···, xj.

在这里插入图片描述

这种情况子问题是 中间的一部分, 所以情况是n*n, 子问题的个数为n^2, 所以用**dp[n][n]**就能把子问题的解保存

扫描二维码关注公众号,回复: 4148585 查看本文章

4.输入为树, 输出为子树

在这里插入图片描述

例子:矩阵链式相乘

假设有4个矩阵A,B,C,D, 每个矩阵的维度依次是50 * 20, 20 * 1, 1 * 10, 10 * 100, 在计算A * B * C * D 的过程中我们可能会利用矩阵相乘的结合率来优化计算,比如我们可能会这样计算 (A * B * C) * D 或者 A * ( B * C )* D , 会得到很多种计算方式,其中有没有什么方式计算量最少呢?
在这里插入图片描述

我们可以看到

在这里插入图片描述

不同方式会产生巨大差异

其实我们可以把不同的计算顺序看成一颗二叉树, 例如在这里插入图片描述

那么子问题就是这个树的子树 动态规划就变成了求子树的最优值。

猜你喜欢

转载自blog.csdn.net/qq874455953/article/details/83747682
今日推荐