1 动态规划
1.1 基本思想
动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题。
与分治法的区别在于,适用于动态规划算法求解的问题,经分解得到的子问题往往不是互相独立的;若用分治法求解,则分解得到的子问题数目太多,导致最终解决原问题需指数时间。原因在于:虽然子问题的数目常常只有多项式量级,但在用分治法求解时,有些子问题被重复计算了许多次,如果可以保存已解决的子问题的答案,就可以避免大量重复计算,从而得到多项式时间的算法。
动态规划法的基本思路是:构造一张表来记录所有已解决的子问题的答案(无论算法形式如何,其填表格式是相同的)。
1.2 适用条件
适用动态规划的问题必须满足最优化原理和无后效性。
最优化原理(最优子结构性质):
最优化原理可这样阐述:一个最优化策略具有这样的性质,不论过去状态和决策如何,对前面的决策所形成的状态而言,余下的诸决策必须构成最优策略。简而言之,一个最优化策略的子策略总是最优的。一个问题满足最优化原理又称其具有最优子结构性质
无后效性:
将各阶段按照一定的次序排列好之后,对于某个给定的阶段状态,它以前各阶段的状态无法直接影响它未来的决策,而只能通过当前的这个状态。换句话说,每个状态都是过去历史的一个完整总结。这就是无后向性,又称为无后效性。
子问题的重叠性:
动态规划算法的关键在于解决冗余,这是动态规划算法的根本目的。动态规划实质上是一种以空间换时间的技术,它在实现的过程中,不得不存储产生过程中的各种状态,所以它的空间复杂度要大于其他的算法。选择动态规划算法是因为动态规划算法在空间上可以承受,而搜索算法在时间上却无法承受,所以我们舍空间而取时间
2 最长子段和问题描述
给定n个整数(可能为负数)组成的序列a1,a2,…,an。求该序列形如下式的子段和的最大值:
![equation?tex=max+%5Csum_%7Bk%3Di%7D%5E%7Bj%7Da_k+%5C%5C](https://i-blog.csdnimg.cn/blog_migrate/14cd1211e75ad7a9e9658c292cd189cb.png)
当所有整数均为负整数时定义其最大子段和为0。 依次定义,所求的最优值为:
![equation?tex=max%5C%7B0%2C%7Bmax%7D_%7B1%5Cleq+i%5Cleq+j%5Cleq+n%7D%5Csum_%7Bk%3Di%7D%5E%7Bj%7Da_k+%5C%7D+%5C%5C](https://i-blog.csdnimg.cn/blog_migrate/dc70bf1053b883b297922357eed52497.png)
例如: (a1,a2,a3,a4,a5,a6)=(-2,11,-4,13,-5,-2) 该序列的最大子段和为:
![equation?tex=%5Csum_%7Bk%3D2%7D%5E4a_k%3D20+%5C%5C](https://i-blog.csdnimg.cn/blog_migrate/5c207c94d57b9914906168a709718f40.png)
3 算法分析
通过对分治算法的分析可知,若记:
![equation?tex=b%5Bj%5D+%3D+%7Bmax%7D_%7B1%5Cleq+i%5Cleq+j%7D%5C%7B%5Csum_%7Bk%3Di%7D%5Ej%7Ba%5Bk%5D%7D%5C%7D%2C1%5Cleq+j+%5Cleq+n+%5C%5C](https://i-blog.csdnimg.cn/blog_migrate/6af9e7d2c31ee9a92ef91ea2a258d3f8.png)
则所求的最大子段和为:
![equation?tex=max_%7B1%5Cleq+j%5Cleq+n%7D%7Bb%5Bj%5D%7D+%5C%5C](https://i-blog.csdnimg.cn/blog_migrate/ebd81d4d64faf70dc69bd3ae9906f731.png)
由b[j]的定义可知: 当
![equation?tex=b%5Bj-1%5D%3E0](https://i-blog.csdnimg.cn/blog_migrate/d1d9c619c124055adb01ea12dd2c1b1e.png)
![equation?tex=b%5Bj%5D%3Db%5Bj-1%5D%2Ba%5Bj%5D+%5C%5C](https://i-blog.csdnimg.cn/blog_migrate/dbdcdeaebd7fb83e27b7187f47e0c09f.png)
否则:
![equation?tex=b%5Bj%5D%3Da%5Bj%5D+%5C%5C](https://i-blog.csdnimg.cn/blog_migrate/5b0e5122ef2e7c75b3114aa0d4bbef56.png)
由此可得b[j]的动态规划递归式:
![equation?tex=b%5Bj%5D%3Dmax%5C%7B+b%5Bj-1%5D%2Ba%5Bj%5D%2C+a%5Bj%5D+%5C%7D+%EF%BC%881%E2%89%A4j%E2%89%A4n%EF%BC%89+%5C%5C](https://i-blog.csdnimg.cn/blog_migrate/1e7e55ac9ff57c9e2a028093c959a575.png)
4 C++实现
int maxSubArray(vector<int>& nums) {
int size=nums.size();
int* b = new int[size];
b[0]=nums.at(0);
for(int i=1;i<size;i++){
if(b[i-1]<0){
b[i]=nums.at(i);
}else{
b[i]=b[i-1]+nums.at(i);
}
}
int maxV=b[0];
for(int i=0;i<size;i++){
if(maxV<b[i]){
maxV=b[i];
}
}
return maxV;
}
![fcb45f1c602997375ec27f053985ff71.png](https://i-blog.csdnimg.cn/blog_migrate/111c75aa608e91a6787c4545ef453482.png)