题目描述
从一组数据(长度为 n,其中 n <= 10000,数据的值都大于 -60000)中找出连续的一段数,使得这段数的和最大。
输入描述
第一行是一个正整数 n,表示数据的个数,从第二行开始是 n 个数据。
输出描述
一行,子段的最大和。
样例输入
5
1 -3 4 1 -9
样例输出
5
AC代码
这是第一次做的时候,当时看数据量不大,就直接用暴力解决
#include<iostream>
using namespace std;
int main()
{
int n;
cin >> n;
int ans = 0; //ans存储最后的答案
int arr[10010]; //存储序列
int i,j;
for (i = 0; i < n; i++)
{
cin >> arr[i];
}
for (i = 0; i < n; i++) //i用来控制子段的第一个数
{
int temp = arr[i]; //temp用来存储从a[i]开始子段的和
for (j = i + 1; j < n; j++) //计算从a[i]开始到最后的子段的和,同时比较ans和temp的大小
{
temp += arr[j];
ans = max(ans, temp);
}
}
cout << ans << endl;
return 0;
}
当数据量较大的时候,可以采用dp来做
接下来附上我后来写的代码
#include<iostream>
using namespace std;
int main()
{
int n;
while(cin>>n)
{
int arr[10010]; //存储序列
int i;
for(i=1;i<=n;i++ )
{
cin >> arr[i];
}
int dp[10010]; //dp数组,存储dp[i]与dp[i-1]+arr[i]之间较大的那一个
//我们可以这么理解,dp数组中存储的是到目前为止的最大的连续子段和,那么我们可以列出这样的转移方程
//dp[i]=max(dp[i-1]+arr[i],arr[i]),对于arr[i]我们无非两种选择,加或不加,呢么我们只要比较一下加与不加那个比较大就行
//如果加上arr[i]比较大,那么dp[i]=dp[i-1]+arr[i],否则,dp[i]=arr[i],因为是连续子段,既然我们不加arr[i],那么我们就要从arr[i]重新开始计算
for(i=1;i<=n;i++ )
{
dp[i]=0;
}
dp[1]=arr[1];
for(i=2;i<=n;i++ )
{
dp[i]=max(dp[i-1]+arr[i],arr[i]); //状态转移方程
}
int ans=dp[1]; //初始化dp[1]
for(i=2;i<=n;i++ )
{
if(dp[i]>ans) ans=dp[i];
}
cout<<ans<<endl;
}
return 0;
}
注:解法一忽略了多组输入,但也能通过评测