动态规划 学习笔记
动态规划
通过把原问题分解成若干个子问题(所有这些问题在一定意 义上答案固定),再利用已知的子问题答案依次计算未知问题的答案,最终得到原问题答案的方式,称之为动态规划(Dynamic Programming,简称 DP)。
动态规划利用若干条信息来标识一个状态,按照一定的顺序 依次计算这些状态对应的答案,每一个状态的计算都利用上之前 计算过的状态(类似递推的由已知得到未知),由此降低问题本身的复杂程度。
动态规划的状态可以笼统的解释为“问题所在的局面”。状态的定义是明确的,具有无后效性以及最优子结构性质。
Luogu P2842 纸币问题 1
用 表示总金额为 时最少用多少张纸币。
如果 ,则可以先用 张纸币凑齐 元,再用一张 元的纸币,即可凑齐 元。
可以得到状态转移方程:
1 | if(i-a[j]>=0) f[i]=min(f[i],f[i-a[j]]+1); |
Luogu P2840 纸币问题 2
用 表示总金额为 时有多少种方式。
如果 ,则有 种方式凑齐 元,再用一张 元的纸币来凑齐 元。
可以得到状态转移方程:
1 | for(int i=1;i<=w;i++) |
Luogu P2834 纸币问题 3
与上一道题相似,但是要求硬币组合的数量。
对于上一道题,我们要保证 是最终答案,因此我们先枚举 再枚举 。
但是这道题,我们要保证 是由编号为 这几种纸币拼出来的方案数,不能有其它纸币参与。
因此我们先枚举 再枚举 即可。
1 | for(int j=1;j<=n;j++) |
Luogu P1216 数字三角形
用 记录到达点 处的最大路径。
而点 可能由 或 直接向下一步走到,于是推出转移方程:
1 | dp[1][1]=a[1][1]; |
Luogu P1048 采药
01 背包模板题。
假设 为物体的体积, 为物体的价值。将这 个物体放入一个体积为 的背包中。
假设 表示将前 个物品放入容量为 的背包中,最大价值是多少。
则有转移方程:
因为有两种选择:选或不选。
若选第 个物体,则前 个物体体积要小于 ,得出 。若不选第 个物体,则等价于只选前 个物体,得出 。
看转移方程。第一维都是 ,于是我们想办法将第一维消掉。
再看第二维,计算 时,第二维的值都小于等于 。要想将第一维消掉,则需要保证,在更新 时, 没有被更新过。
于是我们可以省掉第一维,然后从大到小遍历 。
1 | for(int i=1;i<=n;i++) |
Luogu P1616 疯狂的采药
完全背包模板题。
与上一题相比,这一题每个物品都有无限个。
上一题倒着遍历,其实还为了保证,更新 时, 没有将第 个物品算进去。因为上一题每件物品只有一个。
而这道题每个物品有无数个,我们恰好要保证:更新 时, 已经将第 个物品算进去。
因此正着遍历即可。
1 | for(int i=1;i<=n;i++) |