赞
踩
动态规划法将待求解问题分解成若干个相互重叠的子问题,每个子问题对应决策过程的一个阶段,一般来说,子问题的重叠关系表现在对给定问题求解的递推关系(也就是动态规划函数)中,将子问题的解求解一次并填入表中,当需要再次求解此子问题时,可以通过查表获得该子问题的解而不用再次求解,从而避免了大量重复计算。
动态规划求解的问题应当具有最优子结构性质:
最优性原理(Optimal Principle):
无论决策过程的初始状态和初始决策是什么,其余的决策都必须相对于初始决策所产生的当前状态,构成一个最优决策序列。
即,在多阶段决策中,各子问题的解只与它前面的子问题的解有关,并且各子问题的解都是相对于当前状态的最优解,整个问题的最优解是由各个子问题的最优解构成。
如果一个问题满足最优性原理通常称此问题具有最优子结构性质。
今天老师非常强调,动态规划问题就是数学问题,数学基础较好的更有优势(然而我并不觉得,虽然数学也不太好,不过动态规划的确很难)。动态规划的特点就是每次将运算结果存储起来,供下次计算使用,求解过程主要是逆向思维,倒推的思想。由结果去想上一步是怎么得到这个结果的,从而建立动态规划函数,求解的时候再正向求解。
也就是说,动态规划每一步的结果状态都由上一步的结果状态决定,关键在于找状态转换函数,即目前有一个最优解,如何增加一个元素得到新的最优解。而上一步又由上上一步决定(倒推思想),所以要求解整个问题,得先从第一步开始求解(正向求解),每一个子问题与原问题的求解方法相同。
动态规划的关键在于找动态规划函数,建立状态转换关系,这一步往往很难,因为很多问题的状态关系并不明显,需要花很多功夫去找,完成这一步就意味着问题解决一大半了。还是举个例子吧,最经典的问题,求最大子序列和:
输入N,表示序列有N个元素,然后输入这N个元素
要求找出这个序列中一个和最大的连续子序列,并输出最大和。
样例输入:
6
-2,11,-4,13,-5,-2
样例输出:
20
一般思路(蛮力法):
子序列起始坐标从0…i,终点坐标从0…i,然后对于每一个子序列再嵌套一个循环求和,用了三层循环,因此时间复杂度为
O
(
n
3
)
O(n^3)
O(n3),效率很低。下面是实现代码:
int maxsum(int n, int *a, int & besti, int & bestj)
{ int sum=0;
for (int i=1; i<=n; i++)//控制子数组开始位置
for (int j=i; j<=n; j++)//控制子数组结束位置
{ int thissum=0;
for (int k=i; k<=j; k++) thissum+=a[k];//子数组循环
if (thissum>sum)
{ sum=thissum; besti=i; bestj=j;}
}
return sum;
}
方法二(动态规划):
假设序列元素数组为a[],我们可以用一个数组b[j],来记录以j号元素结尾的子序列的最大和。现在开始找状态函数。假设b[j-1]已经求的,现在求解b[j],那么对于j号元素a[j]结尾的子序列最大和有两种情况,一种是加上b[j-],另一种是直接赋值为a[j]。因为对于j好元素结尾的子序列必然包含a[j],题目有要求是连续子序列,因此现在考虑将以j-1号元素结尾的子序列作为以j号元素结尾的子序列的前缀所形成的新子序列和
b
[
j
−
1
]
+
a
[
i
]
b[j-1]+a[i]
b[j−1]+a[i]是否大于不将其作为以j号元素结尾的子序列的前缀所形成的新子序列和
a
[
i
]
a[i]
a[i],选择最大值即可。由此可以得到状态转移函数:
b[j]=max(b[j-1]+a[j],a[j]);
也可写成
if(b[j]>0)
b[j]+=a[j];
else
b[j]=a[j];
然后不断更新最大值即可。可以发现,动态规划算法的时间复杂度为 O ( n ) O(n) O(n),只用了一层循环,效率是非常高的。以下是实现代码
int maxsum(int n, int *a)
{
int sum=0, b=0;
for (int i=1; i<=n; i++)
{ if (b>0) b+=a[i];
//如果前面为零,相加则影响后面结果,所以抛弃前面总和
else b=a[i];
if(b>sum) sum=b;}
return sum;
}
动态规划的应用非常广,可以解决很多问题,以下是一些经典问题,在各大oj上也都有对应的训练题。
问题描述:给定n个物品,每个物品有两个属性,价值
v
i
v_i
vi和重量
w
i
w_i
wi,给定背包容量
c
c
c,问如何选择物品放入背包使得背包总价值最大。
约
束
条
件
:
{
∑
i
=
1
n
w
i
x
i
≤
c
x
i
∈
{
0
,
1
}
1
≤
i
≤
n
约束条件:\left\{
目
标
函
数
:
m
a
x
∑
i
=
1
n
v
i
x
i
目标函数:max\sum_{i=1}^nv_ix_i
目标函数:maxi=1∑nvixi
问题描述:给定一个 n × n n\times n n×n的矩阵,求解其最大和的子矩阵,输出最大和
问题描述:从数塔的顶层出发,在每一个结点可以选择向左走或向右走,一直走到最底层,要求找出一条路径,使得路径上的数值和最大。
问题描述:给定一个含n个元素的序列,求解其最长的递增序列的长度。
问题描述: 给定n个矩阵{A1, …,An}, 其中Ai与A i-1 是可相乘的. 确定一个计算次序, 使计算矩阵连乘积A1…An所需计算量最少
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。