Dynamaic Programming
定义:
动态规划是运筹学中用于求解决策过程中的最优化数学方法。作为算法设计技术,是一种使用多阶段决策过程最优的通用方法。是解决最优化问题的重要工具。
动态规划的特性:
- 无后效性
- 最优子结构
如何设计DP
动态规划的本质,是对问题状态的定义和状态转移方程的定义
-
1.设计状态,实现状态的定义
-
2.找到状态转移方程
-
动态规划三要素:
问题阶段
每个阶段的状态
一个阶段如何进入下一个阶段的递推关系式
多阶段决策问题
初始状态(
ightarrow)决策1(
ightarrow) 决策2 (
ightarrow)........(
ightarrow)决策n(
ightarrow)结束状态
什么样的问题适用DP
-
1)问题是由交叠的子问题所构成,大问题分解为小问题。
-
2)将交叠子问题的一次次求解( ightarrow)子问题只求解一次,并将结果记录保存。
-
3)利用空间(子问题存储)来换取时间
实现案例分析
信件错排问题
有 N 个 信 和 信封,它们被打乱,求错误装信方式的数量
1.状态定义:
dp[i] 表示前 i 个信和信封的错误方式数量
2.状态转移方程:
假设第 i 个信装到第 j 个信封里面,而第 j 个信装到第 k 个信封里面。根据 i 和 k 是否相等,有两种情况
- i==k,交换 i 和 k 的信后,它们的信和信封在正确的位置,但是其余 i-2 封信有 dp[i-2] 种错误装信的方式。由于 j 有 i-1 种取值,因此共有 (i-1)*dp[i-2] 种错误装信方式
- i != k,交换 i 和 j 的信后,第 i 个信和信封在正确的位置,其余 i-1 封信有 dp[i-1] 种错误装信方式。由于 j 有 i-1 种取值,因此共有 (i-1)*dp[i-1] 种错误装信方式。
状态转移方程为
[dp[i]=(i-1)*dp[i-2] + (i-1)*dp[i-1]
]
问题求解
先从最简单的剪绳子(integer break product maximun)问题
int maxProductLength(int length){
// 先进行判断
if(length<2) return 0;
if(length==2) return 1;
if(length==3) return 2;
// 定义一个数组,存储各个值
// 交叠的子问题 的初始化
int* product=new int[length+1];
product[0]=0;
product[1]=1;
product[2]=2;
product[3]=3;
// 定义一个储存最大值的变量
int max=0;
for(int i=4;i<length;++i){
max=0;
for(int j=1;j<=i/2;++j){
// 递推的表达式
int product=product[i]*product[i-j];
if(product>max)
max=product;
}
product[i]=max;
}
max=product[length];
delete[] product;
return max;
}
补充知识点:
多阶段决策过程:
- 百科:多阶段决策是指决策者在整个决策过程中做出时间上先后有别的多项决策。它通常比只需做出一项决策的单阶段决策要复杂,它或是要决策者一次确定各阶段应选择的一串最优策略,或是找出表示一个过程内连续变化的一条控制变量曲线,或是确定适合不同状态的灵活策略
- 总结:一次决策可以得到解的一部分,当做完所有决策就得到相应完整的解