算法第三章上机实践报告

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个整数。

输出格式:

输出最大子段和。

1.2 算法描述

建立一个d数组,用原数组的值把d初始化。然后从n-1开始判断d[i+1]是否大于0:是,则说明子结构的值为正加上可以得到更大值,d[i]=x[i]+d[i+1];不是,则为负,不加,d[i]=x[i]。再在开始int max=0;每次比较max与d【i】,记录下最大值。

1.3 问题求解:

#include<iostream>
using namespace std;
int main(){
int n,max=0;
cin>>n;
int x[n];
int d[n];
for(int i=1;i<=n;i++){
cin>>x[i];
d[i]=x[i];
}
for(int i=n-1;i>=1;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 根据最优子结构性质,列出递归方程式,

d[ i ] = max { d[ i+1] + x[ i ] , x[ i ] }

1.1.2 给出填表法中表的维度、填表范围和填表顺序。

表d的维度是n,范围是0~n-1,填表顺序是从后n-1的位置开始先前填写到0的位置。

1.1.3 分析该算法的时间和空间复杂度

时间复杂度:只有单循环,所以时间复杂度为O(n)

空间复杂度:表d的大小与a一致,所以空间复杂度为O(n)

1.3 心得体会(对本次实践收获及疑惑进行总结)

每一个位置开始的最大字段和与他的后一个位置的最大字段和有关,符合最优子结构。于是可以从最后位置的数开始自底向上的填表,可以动态规划。这个特点很明显,所以直接就知道了用动态规划的思想来实现。但是自己实现却有的点会卡住,不知道应该怎么写下去了,所以看了课本以及北航的网课,了解自己想法的不足之处。

2. 你对动态规划算法的理解和体会

对于一个问题还是比较容易确定是否采用动态规划的,因为它是用来求最优值的,一旦题目中有和最优相关的词语就得考虑一下它了。但是动态规划定义虽然简单,用起来却是另一回事。即使你知道要用动态规划却不一定真正根据题目应用好。还有就是状态方程的编写和边界条件的考虑问题是比较难以想出来的。

使用一维的dp数组解题时还算是比较好理解,但是到了二维的开始,因为填表顺序的不同,最值可能是上面,可能是下面,这就需要我们对于题目以及自己状态方程的很了解才行。

posted @ 2021-10-26 21:57  涂一波  阅读(16)  评论(0编辑  收藏  举报