动态规划求最大子序列
来源:互联网 发布:mac手写输入法快捷键 编辑:程序博客网 时间:2024/05/01 05:40
动态规划算法两要素
•递归方程式(状态转移方程式)
•保存子问题的解
无穷数列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 中的较大者
•递归方程式(状态转移方程式)
•保存子问题的解
无穷数列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 中的较大者
- 动态规划求最大子序列
- 【动态规划】求最大上升子序列
- 动态规划:求一个序列的最大子序列和
- 动态规划法求最大子序列和
- 动态规划方法求最大公共子序列
- hdu 1087 动态规划 求最大递增子序列
- max sum(动态规划求最大连续子序列)
- HDOJ 1003 MaxSum(动态规划 求最大子序列和)
- 【动态规划】最大子序列
- 求最大子序列长度及最大字段和 --动态规划法C++语言
- 动态规划之最大连续子序列
- [acm]动态规划-最大连续子序列
- 动态规划---hdu1231---最大连续子序列
- HDU1231 最大连续子序列(动态规划)
- 动态规划:最大连续子序列乘积
- 和最大子序列---动态规划
- [动态规划]最大连续子序列和
- 动态规划之最大子序列和
- ubuntu网速很慢的问题解决(firefox)
- OnItemClick各个参数的作用
- android设置背景平铺
- CSS display Property
- Matlab绘制直方图以及均衡化
- 动态规划求最大子序列
- android之间传递多个对象
- Ubuntu显示网络已禁用
- Android中解决输入法问题
- Java编译错误“No enclosing instance of type AA is accessible. Must qualify the alloc
- WindowsPhone中的VoiceCommand
- $().ready onload
- 这只是一篇博客
- MAC下终端sqlite3简单使用