动态规划
type
status
date
slug
summary
tags
category
icon
password
类别
内容
入门DP
- 如果某一问题有很多重叠子问题,使用动态规划是最有效的。
- 动态规划中,每一个状态一定是有上一个状态推导出来的,这一点区分于贪心。
动态规划五步曲
- 状态表示:确定dp数组以及下标的含义
- 状态计算:确定递推公式
- 初始化:dp数组如何初始化
- 确定遍历顺序
- 动态演示:举例推导dp数组(草稿纸或打印输出)
后续的DP问题中,不会详细写出动态规划五步曲,主要注重状态表示,状态计算以及状态初始三部分,其它做到自己做到心里有数即可
背包DP

由上图可知,背包问题的不同,是根据每个物品的数量来决定的
完全背包
每件物品有无穷多个
- 状态表示

- 状态计算

- 遍历顺序

这里同样可以使用滚动数组来进行一维优化,但这里不用要求背包容量j一定要从大到小遍历,因为我们可以从下图看出,完全背包虽然会使用到前面容量较小的背包,造成同一件物品添加多次,但这正是完全背包允许的呀


多重背包
第i中物品最多有si件
- 状态表示

- 状态计算——增加一层循环,对物品数量进行选择,进而转换为01背包问题
由于三重循环,会导致时间复杂度过高,当数据量过大时,会造成超时,因此接下来使用 来去掉第三重循环


另外可以通过 来进行优化
混合背包
题目中,同时存在01背包、完全背包和多重背包
解题策略:在数据输入时,先将多重背包通过二进制拆分转换01背包,然后DP时,分成01背包和完全背包两种问题进行解决
分组背包
物品在不同的组中,且每一组至多选择一件物品
- 状态表示

- 状态计算

线性DP
最长上升子序列
- 状态表示:f[i]表示以第i个元素结尾的最长上升子序列的长度
- 状态计算:f[i] = max(f[i], f[j] + 1;
最长公共子序列
- 状态表示:f[i][j]表示以i位结尾的字符串和以j为结尾的字符串的最长公共子序列长度
- 状态计算
- f[i][j] = max(f[i][j], f[i - 1][j - 1] + 1);
- f[i][j] = max(f[i - 1][j], f[i][j - 1]);
提高:输出最长公共子序列


最长公共字串
区分序列和字串
- 公共序列:不要求连续
- 公共字串:要求连续
- 状态表示:f[i][j]表示以i为结尾的字符串和以j为结尾的字符串的最长公共字串的长度
- 状态计算:
- f[i][j] = 0;
- f[i][j] = max(f[i][j], f[i - 1][j - 1] + 1);
区间DP
【模板题】石子合并
- 状态表示

- 状态计算



- 初始状态

环形石子合并

这道题目和模板题的区别就在于一个是线性,一个是成环的,这时候我们很自然可以想到,在每个两点之间切断,变成线性之后使用模板代码即可:

时间复杂度过高,会超时
环形转化为链形:复制一遍数组,转化为长度为2N的链形数组
初始化会有所不同


能量向量

注意此题与环形石子合并的区别:
- 环形石子合并的代价都在石子本身
- 此题的代价都在项链石子的两侧,所以主体变为了两侧的能量值,不用进行初始化,个数也由n变为了n + 1,同时l,r两个也对应发生了改变
- 同时注意:这里的能量计算,必须涉及左、右、中三者之积,所以l < k < r,k不能取边界值
树形DP
概念
线性DP子结构是一条线段,树形DP子结构是一颗子树
一般思路:从分析子树入手
- 状态表示通常是与子树根节点u有关的函数
- 状态计算就是寻找根点与子节点以及边权的递推关系
- 编写代码时,通常要dfs,从根到叶,再从叶到根,在合适的地方DP
概念不容易入手时,建议从题目入手
没有上司的舞会
- 题目示意图

- 状态表示

- 状态计算

- 代码编写

- 代码推演

有依赖的背包
状压DP
概念
核心:用二进制表示状态,用十进制数存储状态
判断约束条件时,要用到 ,学习状压DP,要先学会简单的位运算
解题思路:
- 列举每行所有的状态(有2^n个状态),找出符合题意的合法状态,然后写出行内合法的位运算表达式
- 找出行间兼容的位运算表达式
- 列出状态表示
- 状态计算
代码编写:
- 先对每一行的合法状态进行预处理
- 多重循环进行状态计算

小国王
- 行内合法

- 行间兼容

- 状态表示

- 状态计算

玉米田
- 行内合法

- 行间兼容

- 状态表示

- 状态计算

炮兵部队
- 行内合法

- 行间兼容

- 状态表示

- 状态计算

数位DP
概念
数位DP特点:求某个区间[L, R]内,满足某种性质的数的个数
解题技巧:
- 类似前缀和的思想,将区间[L, R]问题转换为[0, R] - [0, L - 1]求解
- 从高位到低位填数,要分类讨论


数字游戏
本题无题目链接,题目如下:(代码在输入方面有些许变化)


- 状态表示

- 状态计算

Windy数
- 状态表示

- 状态计算



记忆化搜索
概念
特点:
- 从上向下的累加和是不能重复利用的
- 从下向上的累加和是能重复利用的
意义:对递归树做了剪枝,搜索过的子树不再重复搜索,直接返回存储值
数字三角形
拓展
- 记录最大和的路径
- 左右走的次数有限制

经观察得:
- n为偶数时,最后一层落在的点一定在n/2或n/2+1
- n为奇数时,最后一层落在的点一定在n/2+1
这个时候只能从上往下遍历了
Last update: 2024-04-07
🎉此博客仅为本人记录生活,技术交流所用🎉
-- 如有侵权,请与我联系 ---
-- 感谢您的支持😁 ---