1. 题目分析
1.1 问题描述
最大子段和
给定n个整数(可能为负数)组成的序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的子段和的最大值。当所给的整数均为负数时,定义子段和为0。
要求算法的时间复杂度为O(n)。
输入格式:
输入有两行:
第一行是n值(1<=n<=10000);
第二行是n个整数。
输出格式:
输出最大子段和。
输入样例:
在这里给出一组输入。例如:
6
-2 11 -4 13 -5 -2
输出样例:
在这里给出相应的输出。例如:
20
1.2 算法描述
数组D存储的是所在下标往右加的最大子段和,数组X存储每个下标所在的数值大小。根据动态规划的思想,为了解决这个问题,可以先将每个下标所在的数值与其右边的最大子段和加起来,然后用max来存储最大的那个。
1.3 问题求解
#include<iostream>
using namespace std;
int main(){
int n, max=0;
cin >> n;
int D[10000]={0};
int X[10000]={0};
for(int i=0; i<n; i++){
cin >> X[i];
}
for(int i=n-1; i>0; i--){
if(D[i+1]>0)
D[i]=X[i]+D[i+1];
else
D[i]=X[i];
if(D[i]>max)
max=D[i];
}
cout << max;
return 0;
}
1.1.1 根据最优子结构性质,列出递归方程式
if(D[i+1]>0) D[i]=X[i]+D[i+1];
else D[i]=X[i];
1.1.2 给出填表法中表的维度、填表范围和填表顺序
维度:一维
填表范围:1到n
填表顺序:从n到1
1.1.3 分析该算法的时间和空间复杂度
for(int i=n-1; i>0; i--){
if(D[i+1]>0)
D[i]=X[i]+D[i+1];
else
D[i]=X[i];
if(D[i]>max)
max=D[i];
}
容易看出,时间复杂度为O(n)
1.2 心得体会(对本次实践收获及疑惑进行总结)
通过这次实验课,明白了自己对于动态规划的理解还是不够深刻,以及递归的一些细节还不够清楚,不过经过队友和老师的点拨,有了更好的理解,也希望自己可以把这章的内容吃透!
2. 你对动态规划算法的理解和体会
我理解的动态规划,即是对一个计算量庞大且需要重复计算的问题,可以先分析其结构,然后寻找递归关系,再由下至上计算,最后找到最优解。学会了如何去使用一个类似于备忘录的东西,去解决需要重复计算的问题,以减少算法的时间。