动态规划入门详解+例题P1049装箱问题/62. Unique Paths
小蒟蒻自己的学习记录,呜呜呜
算法思想
动态规划是一种分治思想,但与分支算法不同的是,动态规划也是把原问题分解为若干子问题,然后自底向上,求解最小的子问题,叭结果存储在表格中,再求解大的子问题时,直接从表格中查询小的子问题的解,避免重复计算,从而提高算法效率。
题目特点/算法要素
-
计数
有多少种方法走到右下角
有多少种方法选出k个数使得和是Sum
-
求最大最小值
从左上角走到右下角路径的最大数字和
最长上升子序列长度
-
求存在性
去石子游戏,先手是否必胜
能不能选出k个数使得和是Sum
性质:
(1)最优子结构
最优子结构性质是指问题的最优解包含其子问题的最优解。最优子结构是使用动态规划的最基本条件,如果不具有最优子结构性质,就不可以使用动态规划解决
(2)子问题重叠
子问题重叠是指在求解子问题的过程中,有大量的子问题时重复的,那么只需要求解一次,然后把结果存储在表中,以后使用时可以直接查询,不需要再次求解。子问题重叠不是使用动态规划的必要条件,但问题存在子问题重叠更能够充分彰显动态规划的优势
做题方法
一、确定状态
解动态规划的时候一般需要开一个数组(一维,二维,三维),数组的每个元素 f [i] 或者 f [i] [j] 代表什么
最后一步: 最优策略的最后一个决策
子问题: 剩下的问题
二、转移方程
三、初始条件和边界情况
初始条件: 用转移方程算不出来的,需要手动定义
边界情况: 不要数组越界,向下越负数和向上越界都不行
四、计算顺序
一维(大多数情况): 从小到大
二维: 从左到右,从上到下
因为计算后面的时候,需要用到前面的数据,前面的需要先计算出来(你要使用的状态一定要先于正在计算的状态计算出来)
例题——P1049 [NOIP2001 普及组] 装箱问题
题目描述
有一个箱子容量为V(正整数,0≤V≤20000),同时有n个物品(0<n≤30,每个物品有一个体积(正整数)。
要求n个物品中,任取若干个装入箱内,使箱子的剩余空间为最小。
输入格式
11个整数,表示箱子容量
11个整数,表示有n个物品
接下来n行,分别表示这n个物品的各自体积
输出格式
11个整数,表示箱子剩余空间。
输入输出样例
输入
24
6
8
3
12
7
9
7
输出
0
说明/提示
【题目来源】
NOIP 2001 普及组第四题
Solution
一、确定状态
转换:最小剩余空间,即最大的可装重量
分别开一个200000的数组和35的数组即可
f ( m - w[i] ) 指在装了物品i后,箱子的剩余容量能装的最大重量
f ( m - w[i] ) + w[i] 指在在装了物品i后,箱子能装的最大重量
最后一步: 最优策略后剩余的最小容量
子问题: 最大重量的物品放入箱子内被装下的最大容量
二、转移方程
f (m) = max ( f ( m - w[i] ) + w[i], f (m) )(w为重量,即价值)
三、初始条件和边界情况
初始条件: 无
边界情况: 不要数组越界,向下越负数和向上越界都不行
四、计算顺序
一维(大多数情况): 从小到大
因为计算后面的时候,需要用到前面的数据,前面的需要先计算出来(你要使用的状态一定要先于正在计算的状态计算出来)
Code
#include <bits/stdc++.h>
using namespace std;
int main()
{
int m,n,i