`
xlover
  • 浏览: 240202 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

动态规划求最大子序列

 
阅读更多
动态规划算法两要素
•递归方程式(状态转移方程式)
•保存子问题的解
无穷数列1,1,2,3,5,8,13,21,34,55,…,称为Fibonacci数列。它可以递归地定义为

             1                               n = 0
F(n) =       1                               n = 1
             F(n – 2) + F(n – 1)       n > 1

保存子问题的解
#define MAX 1000
__int64 temp[MAX] = {0};
__int64 fibonacci(int n)
{
int i = 0;
temp[0] = 1;
temp[1] = 1;
for(i=2; i<= n; i++)
{
temp[i] = temp[i-1] + temp[i-2];
}
return temp[n];
}

基本思想:将待求解的问题分解成若干个相互联系的子问题,先求解子问题,然后从这些子问题的解得到原问题的解(多阶段决策);
对于重复出现的子问题,只在第一次遇到的时候对它进行求解,并把答案保存起来,让以后再次遇到时直接引用答案,不必重新求解 (填表)。

动态规划算法步骤

(1)找出最优解的性质,并刻画其结构特征。
(2)递归地定义最优值
(3)以自底向上的方式计算出最优值
(4)根据计算最优值时得到的信息,构造一个最优解

例子1:最大子段和
最大字段和问题,即给定n个整数(可能有0和负数)组成的序列a1 a2 a3.......an, 求其最大连续子段和。如有(-2, 11, -4, 13, -5, -2),则最大子段和 11-4+13=20。

#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
#define N 14
int MaxSumDP(int *a, int n);                    //动态规划法
int a[N] = {9, -7, 3,-1, 4, 5, -10, -2, 9, 1, -3, -4, 6, 2};
int b[N];//b[i]表示以a[i]为最后一个元素的最大子段和


int main()
{
       
         printf("The MaxSubSum using DP: %d\n", MaxSumDP(a, N));
         getchar();
         return 0;
}


int MaxSumDP(int *a, int n)                                     //动态规划法
{
         int i, maxSum = 0;
         if(a[0] > 0)
                 maxSum=b[0]=a[0];

         for(i=1; i<n; ++i)
         {
                 b[i] = (b[i-1]+a[i] > 0) ? (b[i-1]+a[i]) : 0;//记录每个子结构的和,如果前面的i-1
                 if(maxSum < b[i])              //已经是小于0,后面的直接赋值就a[i]
                         maxSum = b[i];
         }

         return maxSum;
}

可以看出动态规划法的复杂度只有O(n),但需要O(n)的空间,而分治法的复杂度是O(nlogn),可见动态规划法更优秀。在动态规划法中,b[n]数组的元素b[i]代表的意思是:
    如果a[0]=0,则b[0]=a[0],否则b[0]=0,然后对于b[i]
    b[i] = MAX( b[i -1] + a[i], 0 );
    即b[i]等于b[i-1]+a[i] 和 0 中的较大者
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics