题目来源:http://acm.hdu.edu.cn/showproblem.php?pid=1231
算法参考:http://blog.163.com/wuguojin03@126/blog/static/17154113120109510946717/
状态:dp[i]:以i为结尾的最大连续序列和
初始状态:dp[i]=a[i]
状态转移:dp[i]=max{dp[i-1]+a[i],a[i]}
要求最大的,只需从dp[i]找出最大值就行了
以本题输入样例 “ -2 11 -4 13 -5 -2 ” 为例:
序号: 0 1 2 3 4 5
a[]: -2 11 -4 13 -5 -2
dp[]: -2 11 7 20 15 13
观察dp[],终点即为 max:20,起点则为从max往前找最后一个不为负的数,即11
AC代码:
#include <iostream> #include <cstdio> #include <string.h> #include <algorithm> using namespace std; const int N=10010; int a[N],dp[N]; int main() { int n; while(cin>>n && n){ int s=0,e=0; for (int i = 0; i < n; ++i){ cin>>a[i]; dp[i]=a[i]; } for(int i=1;i<n;++i){ dp[i]=max( dp[i-1]+a[i] , a[i] ); } //查找最大和及终点 int mymax=-1; for (int i = 0; i < n; ++i){ if(mymax<dp[i]){ mymax=dp[i]; e=i; } } //查找起点 for(int i=e;i>=0;--i) if(dp[i]<0){ s=i+1; break; } if(mymax<0)cout<<"0 "<<dp[0]<<" "<<dp[n-1]<<endl; else cout<<mymax<<" "<<a[s]<<" "<<a[e]<<endl; } return 0; }
一年后,偶遇此题又做一遍,用的是双dp,效率还没有上面的高:
#include <algorithm> #include <cstdio> using namespace std; const int MAXN=10000+5; int a[MAXN],dp_l[MAXN],dp_r[MAXN]; int n; int main() { while(scanf("%d",&n)&&n>0) { for(int i=0;i<n;++i){ scanf("%d",&a[i]); } dp_l[0]=a[0]; dp_r[n-1]=a[n-1]; int ans=a[0],start=0,end=n-1; for(int i=1;i<n;++i){ dp_l[i]=max(a[i],a[i]+dp_l[i-1]); if(dp_l[i]>ans){ ans=dp_l[i]; end=i; } } ans=a[0]; for(int i=n-2;i>=0;--i){ dp_r[i]=max(a[i],a[i]+dp_r[i+1]); if(dp_r[i]>=ans){ ans=dp_r[i]; start=i; } } if(ans<0){ ans=0;start=0;end=n-1; } printf("%d %d %d ",ans,a[start],a[end] ); } return 0; }
还有一种方法,也挺快,不过不是用的动态规划:
#include <algorithm> #include <cstdio> using namespace std; const int MAXN=10000+5; int a[MAXN],dp_l[MAXN],dp_r[MAXN]; int n; int main() { while(scanf("%d",&n)&&n>0) { for(int i=0;i<n;++i){ scanf("%d",&a[i]); } int start=0,end=n-1,left,ans=a[0],sum=0; for(int i=0;i<n;++i){ if(sum<0) { //如果前几项和小于0,就重新开始记录 sum=0; left=i; //刷新临时起点 } sum+=a[i]; if(sum>ans){ //如果现在的sum大于原来的max,刷新数据 ans=sum; start=left; end=i; } } if(ans<0){ ans=0;start=0;end=n-1; } printf("%d %d %d ",ans,a[start],a[end] ); } return 0; }