HDU 1231 最大连续子序列

状态表示:dp[i]是必须以A[i]结尾的连续序列。

那么只有两种情况:

  1. 这个最大和的连续序列只有一个元素,即以A[i]开始,以A[i]结尾。
  2. 这个最大和的连续序列有多个元素,即从前面某处A[p]开始(p<i),一直到A[i]结尾。

对第一种情况,最大和就是A[i]本身。
对第二种情况,最大和是dp[i- 1]+A[i],即A[p] +...+ A[i- 1]+ A[i]= dp[i- 1] + A[i]。

由于只有这两种情况,于是得到状态转移方程:

\[dp[i] = \max(A[i],dp[i-1]+A[i]) \]

这个式子只和i与i之前的元素有关,且边界为dp[0]= A[0],由此从小到大枚举i,即可得到整个dp数组。接着输出dp[0], dp[1],... , dp[n - 1]中的最大值即为最大连续子序列的和。

除了需要求出最大连续子序列的值外还需要输出最大连续子序列的第一个和最后一个元素。

用两个变量from和to记录循环到以第\(i\)个元素结尾的最大连续子序列时的左、右元素,from和to伴随着\(i\)的右移进行迭代更新。

若所有K个元素都是负数,则定义其最大和为0,输出整个序列的首尾元素。

const int N=10010;
int a[N];
int f[N];
int n;

int main()
{
    while(cin>>n, n)
    {
        for(int i=0;i<n;i++) cin>>a[i];

        f[0]=a[0];
        int ans=a[0];
        int from=a[0],to=a[0];
        int ansl=a[0],ansr=a[0];
        for(int i=1;i<n;i++)
        {
            if(f[i-1]+a[i] > a[i])
            {
                f[i]=f[i-1]+a[i];
                to=a[i];
            }
            else
            {
                f[i]=a[i];
                from=to=a[i];
            }
            if(f[i] > ans)
            {
                ans=f[i];
                ansl=from;
                ansr=to;
            }
        }
        
        if(ans < 0) cout<<0<<' '<<a[0]<<' '<<a[n-1]<<endl;
        else cout<<ans<<' '<<ansl<<' '<<ansr<<endl;
    }
    //system("pause");
    return 0;
}
posted @ 2021-02-01 19:43  Dazzling!  阅读(50)  评论(0编辑  收藏  举报