动态规划求最大子序列

[size=large]动态规划算法两要素
•递归方程式(状态转移方程式)
•保存子问题的解
无穷数列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 中的较大者[/size]
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值