第三章算法上机实践报告
1.1 问题描述
最大子段和
给定n个整数(可能为负数)组成的序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的子段和的最大值。当所给的整数均为负数时,定义子段和为0。
要求算法的时间复杂度为O(n)。
1.2 算法描述
设计a数组来存放书籍以及D数组来记录当前以i开头的最大子段和。
1、若D[i+1]>0,D[i]=D[ i+1] + a[i]
2、若D[i+1]<0,D[i]=a[i]
3、根据最优子结构性质,列出递归方程式,D[ i ] = max { D[ i+1] + a[ i ] , a[ i ] }
4、同时定义max来记录D中的最大值,并用0来初始化max,因为题目要求当所给的整数均为负数时,定义子段和为0。
5、输出max即为题目所求的最大子段和
#include <iostream>
using namespace std;
int main()
{
int a[100]={0};
int D[100]={0};
int max=0;
int n;
cin >> n;
for(int i=0; i<n ;i++)
cin >> a[i];
D[n-1]=a[n-1];
for(int i=n-1;i>=0;i--)
{
if(D[i+1]>0)
D[i]=a[i]+D[i+1];
else
D[i]=a[i];
}
for(int i=n-1;i>=0;i--)
{
if(max < D[i])
max = D[i];
}
cout <<max;
}
1.3 问题求解:
1.1.1 根据最优子结构性质,列出递归方程式
D[ i ] = max { D[ i+1] + a[ i ] , a[ i ] }
1.1.2 给出填表法中表的维度、填表范围和填表顺序。
D是一个一维数组,长度与a数组相同,我们令D[n-1]=a[n-1],从后往前填写,填写的为范围是下标0至n-1。
1.1.3 分析该算法的时间和空间复杂度
时间复杂度:与n有关的for循环,故为O(n)
空间复杂度:开设了一个大小为n的数组存放当前下标的最大子段和,与n有关,故为O(n)
1.3 心得体会(对本次实践收获及疑惑进行总结)
这道题一开始没有什么头绪,是看北航老师的视频才学会的,学会D(i)数组的存放以及表达,用来表示某一段的最大子段和,这种分段存放的思想在后面的很多题目中都能用到。
2. 你对动态规划算法的理解和体会
1)在做动态规划的问题的时候要根据这四步来分析:1、分析问题的结构 2、建立递推关系 3、自底向上计算 4、选择最优方案
2)我们做动态规划的题目的时候是一定能写出递归方程式的,在实验课上我知道了,有些题目虽然你会写,能简单的将题目看出来,但不一定是用了动态规划的方法,所以我们一定要先写出方程式再去打代码。
3)动态规划常用于解最值问题,且该问题可以被分解成小问题有且只求解一次,如果满足这两个条件我们就可以用动态规划了。