算法第三章实践报告

1.1 题目描述

7-1 最大子段和 (25 分)
 

给定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 算法描述

用s[]数组来储存最大字段和,a[]储存输入数组。若s[i-1]小于0,则舍弃前面的和,从a[i]重新开始加和;否则继续将a[i]累加到s[i-1]上,s[i]=s[i-1]+a[i]。
据题目要求“当所给的整数均为负数时,定义子段和为0。”,我利用变量flag来统计数组a里负数的个数,若flag=n,即全为负数。
 
1.3 问题求解
代码:

#include<iostream>
using namespace std;
int main()
{
int n,a[100000],s[100000];
int max=-1;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}

int flag=0;
s[1]=a[1];
for(int i=1;i<=n;i++)
{
if(a[i]<0) flag++;
}
if(flag=n) max=0;
for(int i=2;i<=n;i++)
{
if(s[i-1]<0) s[i]=a[i];
else s[i]=s[i-1]+a[i];
}
for(int i=1;i<=n;i++)
{

if(s[i]>max) max=s[i];
}
cout<<max;
return 0;
}

1.3.1 递归方程式

if(s[i-1]<0) s[i]=a[i];
else s[i]=s[i-1]+a[i];

1.3.2 填表法中表的维度、填表范围和填表顺序

1*n的表格,从s[1]填到s[n]

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

for(int i=2;i<=n;i++)
{
if(s[i-1]<0) s[i]=a[i];
else s[i]=s[i-1]+a[i];
}
for(int i=1;i<=n;i++)
{

if(s[i]>max) max=s[i];
}

仅进行了一次n-1次和一次n次的循环,所以时间复杂度为O(n)

空间复杂度为O(n)

1.4心得体会

动态规划问题往往是求最大或最小即最优解的问题,用整形变量max或其他变量名代替数组作最后的输出,在面临一些特殊情况后者临界条件时会比较好操作。

 

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

动态规划法就是通过递归思想外加变量来储存已经计算过的结果,再在后面将这些结果重新利用起来,减少大量的重复运算。

 

posted on 2021-10-26 19:06  lyxnov  阅读(14)  评论(0编辑  收藏  举报

导航