动态规划与分治的基本思想一致,都是将整个问题分解为子问题,然后解子问题进而求得原问题。然而,两者又有本质的不同:
分治中的子问题相互独立,解得所有子问题后,组合起来就是原问题;
动态规划中的子问题不是相互独立的,后一个子问题的解往往要用到前一个子问题的解。这从下面要分析的最长子串问题中可以看得很清楚。动态规划从一个最简单的子问题着手,然后每一步的结果都被保存,供下一个子问题使用。
动态规划只适用于具有最优子结构的问题,即,局部最优解能决定全局最优解。这样,我们才能将其划分为子问题来解决。
动态规划总体上来说是一个多阶段决策过程,而且这个决策问题应该具有马尔科夫性,即(下一个决策只与前一个决策有关)。下面提到的最优化原理,就是指“最优过程的部分也一定是最优的”
求解步骤
- 最优子结构性质。如果问题的最优解所包含的子问题的解也是最优的,我们就称该问题具有最优子结构性质(即满足最优化原理)。最优子结构性质为动态规划算法解决问题提供了重要线索。
- 子问题重叠性质。子问题重叠性质是指在用递归算法自顶向下对问题进行求解时,每次产生的子问题并不总是新问题,有些子问题会被重复计算多次。动态规划算法正是利用了这种子问题的重叠性质,对每一个子问题只计算一次,然后将其计算结果保存在一个表格中,当再次需要计算已经计算过的子问题时,只是在表格中简单地查看一下结果,从而获得较高的效率。
- 最终,我们可以得到下面这个递归式:f(k,x) = h( d, f(k-1,x-1) ) 其中k表示迭代次数,其中h是求当前最优解的一个函数,f(k,x)表示第k次的最优值,d表示问题变化的量。
先把代码贴上来吧,明天再解释。
最长子串:
其实,动态规划的思路就是每一步都求子问题的最优解,然后迭代到最后就是整个问题的最优解。求最长子串的思路也一样,我们从串的第一个值开始,每次都选取最大的子串。
假设有子串a1,a2.....an ,我们已经求得子串a1......aj(1<= j <= n)的最长子串是b , 那么我们现在记录b的值,然后计算a1 ....aj,a(j+1)【其实这个子串可以看做是 b, a(j+1)】的最长子串,那么它的最长子串就是 b+a(j+1)和a(j+1) 中的较大者。
1 #include <iostream>
2 #include <vector>
3 using namespace std;
4
5
6 //最长子串
7 double longest( vector<double> vect)
8 {
9 vector<double>::iterator iter;
10
11 double sum = -65535;
12 double b = 0;
13
14 for ( iter=vect.begin(); iter!=vect.end(); ++iter )
15 {
16 b = max( b+*iter, *iter);
17 if( b>sum ) sum = b;
18 }
19 return sum;
20 }
21 int main( )
22 {
23 vector<double> vect;
24 vect.push_back(-1);
25 vect.push_back(2);
26 vect.push_back(-3);
27 vect.push_back(9);
28 vect.push_back(1);
29
30 double sum = longest(vect);
31
32 cout << "sum = " << sum << endl;
33 }
最大子矩阵,需要调用上面的函数:
最大子矩阵的思想与最长子串的思想类似。我们想借助求最长子串的方法来求最大矩阵,假设矩阵为m*n,我们将每一行(总共n个数据)看做一个串,如果求这个串的最大子串,那么就是一个子最优矩阵。其实这里我们还是用了穷举的方法,我们要计算所有这样的串的最长子串。而对于其他子矩阵,我们又怎样将它转化为串呢?这里有一个比较好的方法。将每一个完整的子矩阵(这里完整的意思是n列)的每一行的相同列相加,然后就构成一个子串了呗。但是这里要计算所有子矩阵的最长子串,所以复杂度不是很低,这个还得好好思考有没有更好的方法
1 #include <iostream>
2 #include <vector>
3 using namespace std;
4
5 #define m 5 //行
6 #define n 6//列
7
8 //最大子矩阵
9 double maxMatrix( double **array )//m*n
10 {
11 double sum = -65535, temp;
12 vector<double> vect(n);
13 for ( int i=0; i<m; ++i )
14 {
15 for ( int j=0; j<n; ++j )
16 {
17 vect[j] = 0;//初始化
18 }
19 for( int j=i; j<m; ++j )
20 {
21 for( int k=0; k<n; ++k)
22 {
23 vect[k] += array[j][k];
24 }
25 temp = longest(vect);
26 if ( temp >=sum )
27 sum = temp;
28 }
29 }
30
31 return sum;
32 }
33 ////测试矩阵的值可以自己写
34 int main( )
35 {
36 int k = 0;
37
38 double **array ;
39 array = new double *[m];
40 for (int i=0; i<m;++i)
41 {
42 array[i] = new double [n];
43 }
44
45 for (int i=0; i<m; ++i)
46 for (int j=0; j<n; ++j)
47 {
48 array[i][j] = k;
49 k++;
50 }
51
52
53 double sum = maxMatrix(array);
54
55 cout << "sum = " << sum << endl;
56
57 return 0;
58
59
60 }