Max Sum HDU - 1003
考察:线性dp
思路:
f[i]定义为以i结尾的连续子序列的最大值,划分集合分为a[i]做起点,或者从前面的最大值连续到a[i],状态转移方程是f[i] = max(f[i-1]+a[i],a[i]).
本题最难的点在找起点和终点(对本蒟蒻而言)....下面的测试数据可以测出代码是不是"短视"了
我们求的ans在前段被更新为较大的值,但真正的ans是从10处开始累加,起始不会>ans,所以需要一个变量记录每一个新开始子序列的start值.
1 15 549 -945 -581 -450 627 744 -642 -964 -788 767 962 602 832 -477 916
1 #include <iostream> 2 #include <cstring> 3 using namespace std; 4 const int N = 100010,INF = -2147483648; 5 int a[N],n,f[N]; 6 int main() 7 { 8 int T,kcase = 0; 9 scanf("%d",&T); 10 while(T--) 11 { 12 scanf("%d",&n); 13 if(kcase) printf("\n"); 14 for(int i=1;i<=n;i++) scanf("%d",&a[i]); 15 int st =1,start = 1,ed =1,ans = a[1]; 16 for(int i=1;i<=n;i++) 17 { 18 f[i] = a[i]; 19 if(f[i-1]+a[i]>=f[i]) 20 {//连续的序列,ed延长 21 f[i] = f[i-1]+a[i]; 22 if(f[i]>ans) ans = f[i],ed = i,st = start; 23 continue; 24 }//新开的序列,st 重新赋值. 25 else{ 26 start = i; 27 if(f[i]>ans) ans = f[i],st = i,ed = i; 28 } 29 } 30 printf("Case %d:\n%d %d %d\n",++kcase,ans,st,ed); 31 } 32 return 0; 33 }