最大子段和的动态规划算法
我们在选择一个元素a[j]的时候,只有两种情况,将a[i]至a[j-1]加上,或者从a[j]以j为起点开始。我们用一个数组dp[i]表示以i为结束的最大子段和,对于每一个a[i],加上dp[i-1]成为子段,或以a[i]开始成为新段的起点。因为我们只需要记录dp值,所以复杂度是O(n)。这就是最大子段和的动态规划算法。
我们甚至不需要dp数组,只需要定义一个dp变量,因为最后要求的dp值也是最大的,所以我们可以在求dp的时候更新为最大的。
样例代码1
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
using namespace std;
int main()
{
int n;
long long a[50005];
//long long dp[50005];
while(scanf("%d",&n)!=-1)
{
for(int i=0; i<n; i++)
{
scanf("%lld",&a[i]);
}
//memset(dp,0,sizeof(dp));
long long ans=0,dp=0;
for (int i=0; i<n; i++)
{
if(dp>0)
dp+=a[i];
else
dp=a[i];
if(dp>ans)
ans=dp;
}
cout<<ans<<endl;
}
return 0;
}
样例代码2
题:http://acm.hdu.edu.cn/showproblem.php?pid=1003
#include<iostream>
#include<string>
using namespace std;
int main(){
long long unsigned T;
cin>>T;
int index=1;
bool flag=false;
while(T--){
int n;cin>>n;
int t;
long long ans=-10003,sum=0;
int x=1,y=1;
int ax=1,ay=1;
for(int i=0;i<n;i++){
cin>>t;
if(sum>=0){
sum+=t;
y=i+1;
}else{
sum=t;
x=i+1;
y=i+1;
}
if(sum>ans){
ans=sum;
ax=x;
ay=y;
}
}
if(flag)cout<<endl; flag=true;
cout<<"Case "<<index<<":"<<endl;
cout<<ans<<" "<<ax<<" "<<ay<<endl;
index++;
}
return 0;
}