Max Sum(hdu-1003)

一道很有意思的dp,说它有意思是因为他的原理其实很简单,而且扫描一次就可以得到最终的答案。

如果当前这个数之前的和小于0,那么最大和就从当前的数重新开始;否则最大和就是之前的和加上当前这个数。

这样为什么是正确的呢? 我们假设当前这个数之前的连续和小于0,那么他对下面的贡献是负的,所以无论后面的数有多大,最大连续和肯定都不如舍弃前面负贡献的和大。

然后每次更新dp[i]的最大值,就相当于由枚举的连续和的终点。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int T,n,a[100005],dp[100005];
int main(){
    scanf("%d",&T);
    int kase = 0;
    while(T--){
        scanf("%d",&n);
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=n;i++) {
            scanf("%d",&a[i]);
        }
        printf("Case %d:\n",++kase);
        int ans = -1000000000,x1,x2,l,r;
        dp[1] = a[1];
        x1 = 1; ans = dp[1];
        l=1; r=1;
        for(int i=2;i<=n;i++){
            if(dp[i-1]<0) {
                x1 = i;
                dp[i] = a[i];
            } else dp[i] = dp[i-1] + a[i];
            if(ans<dp[i]){
                ans = dp[i];
                l = x1; r = i;
            }
        }
        printf("%d %d %d\n",ans,l,r);
        if(T) printf("\n");
    }
    return 0;
}


你可能感兴趣的:(ACM,hdoj)