动态规划总结:7种dp + 模板

本篇文章主要总和动态规划中常见类型的模板,详细的讲解在每个知识点下的链接中。

目录

1-背包问题

 01背包:

 完全背包:

 多重背包:

2-线性dp

 数字三角形 

 最长上升子序列 ( LIS )

 最长公共子序列(Lcs)

 最短编辑距离:

3-区间动态规划


入门

   动态规划是从暴力dfs慢慢优化出来的算法,以本篇入门了解dp思想,之后再系统学习各类。

动态规划入门:从暴力dfs到dp-CSDN博客

从跳台阶开始dp优化:三种解法 + 详细解读-CSDN博客

 递归与递推:

  • 递归:自上向下,把问题分解为子问题,直到分解到最下,通过记录子问题的解,来使下次碰到子问题时直接使用之前的记录
  • 递推:自底向上,从边界出发,不断向上解决问题

1-背包问题 

  注意! 

  •   一维dp中,01背包和多重背包的j是从V~0遍历,完全背包是从0~V   
  • 存储时都要从1开始,因为涉及到i - 1的处理

 01背包:

从01背包开始动态规划:暴力解法 + dp + 滚动数组 + dp优化-CSDN博客

f [ i ] [ j ] 表示在选到第 i 个物品,背包剩余体积为 j 时的最大总价值

二维数组:

 for(int i = 1;i <= n;i++){
        for(int j = 0;j <= V;j++){
            f[i][j] = f[i - 1][j];
            if(j >= v[i])
                f[i][j] = max(f[i][j],f[i - 1][j - v[i]] + w[i]);
        }
    }

一维数组:

for(int i = 1;i <= n;i++){
        for(int j = V;j >= 0 ;j--){
            if(j >= v[i]) {
                f[j] = max(f[j],f[j - v[i]] + w[i]);
            }
        }
    }

 完全背包:

完全背包的动态规划:暴力dfs + dp + dp优化-CSDN博客

二维数组:

for(int i = 1;i <= n;i++){
        for(int j = 0;j <= V;j++){
            f[i][j] = f[i - 1][j];
            if(j >= v[i])
                f[i][j] = max(f[i - 1][j],f[i][j - v[i]] + w[i]);
        }
}

一维数组:

 for(int i = 1;i <= n;i++){
        for(int j = 0;j <= V;j++){
            if(j >= v[i])
                f[j] = max(f[j],f[j - v[i]] + w[i]);
        }
    }

 多重背包:

多重背包的动态规划:暴力dfs + dp + dp优化-CSDN博客

二维数组:

for(int i = 1;i <= n;i++){
        for(int j = 0;j <= V;j++){
           f[i][j] = f[i - 1][j];
            for(int k = 1;k <= s[i];k++){
                
                if(j >= v[i] * k)
                    f[i][j] = max(f[i][j],f[i - 1][j - v[i] * k] + w[i] * k);
            }
            
        }
    }

一维数组:

 for(int i = 1;i <= n;i++){
        for(int j = V;j >= 0;j--){
            for(int k = 1;k <= s[i];k++){
                
                if(j >= v[i] * k)
                    f[j] = max(f[j],f[j - v[i] * k] + w[i] * k);
            }
            
        }
    }

2-线性dp

线性dp是指所有的状态转移方程之间存在线性关系,即可以通过计算来求出结果

 数字三角形 

动态规划入门:从暴力dfs到dp-CSDN博客

f[ i ] [ j ]表示到第i行第i列的最大和,本题采用倒序,即从树的最下面开始遍历

二维数组:

for (int i = n - 1; i >= 0; i--) {
		for (int j = 0; j < n; j++) {
			f[i][j] = max(f[i + 1][j], f[i + 1][j + 1]) + mp[i][j];
		}
	}

一维数组:

for (int i = n - 1; i >= 0; i--) {
		for (int j = 0; j < n; j++) {
			f[j] = max(f[j], f[j + 1]) + mp[i][j];
		}
	}

 最长上升子序列 ( LIS )

最长上升子序列的动态规划:暴力dfs + 记忆化搜索 + dp-CSDN博客

f [ i ] 表示以第i个数为结尾,最长的上升子序列个数。然后对i之前的数进行遍历,以此求出f [ i ]

 for(int i = 0;i < n;i++){
        f[i] = 0;
        for(int j = 0;j < i;j++){
            if(nums[j] < nums[i])
                f[i] = max(f[i],f[j] + 1);
        }
        res = max(res,f[i]);
    }

 最长公共子序列(Lcs)

最长公共子序列详解:状态表示的两种方法-CSDN博客

本题有两种状态表示的方法,将其分类为a[ i ] 与 b[ i ] 是否相等更便于理解

 for(int i = 1;i <= m;i++){
        for(int j = 1;j <= n;j++){
            if(a[i] == b[j]) f[i][j] = f[i - 1][j - 1] + 1;
            else f[i][j] = max(f[i - 1][j], f[i][j - 1]);
        }
    }

 最短编辑距离:

最短编辑距离:递推公式详解-CSDN博客

 for(int i = 1;i <= n;i++){
        for(int j = 1;j <= m;j++){
            f[i][j] = min(f[i - 1][j],f[i][j - 1]) + 1;
            if(a[i] == b[j]) f[i][j] = min(f[i][j],f[i - 1][j - 1]);
            else f[i][j] = min(f[i][j],f[i - 1][j - 1] + 1);
        }
    }

3-区间动态规划

石子合并与果子合并:区间动态规划和贪心-CSDN博客

 for(int len = 2;len <= n;len++){
        for(int i = 1;i + len - 1 <= n;i++){
            int l = i,r = i + len - 1;
            f[l][r] = 1e8;
            for(int k = l;k < r;k++)
                f[l][r] = min(f[l][r],f[l][k] + f[k + 1][r] + s[r] - s[l - 1]);
        }
    }

以上是本文全部内容,如果对你有帮助点个赞再走吧~  ₍˄·͈༝·͈˄*₎◞ ̑̑

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值