1. 程式人生 > >dp經典問題-最大連續子序列和 hdu1003

dp經典問題-最大連續子序列和 hdu1003

題目描述:

這道題我先後做過三遍,結果每一遍都沒有做出來。今天再仔仔細細的研究了一下,才發現用動態規劃更好理解。

關於求最大連續子序列和的博文轉載如下:https://www.cnblogs.com/coderJiebao/p/Algorithmofnotes27.html

最大連續子序列和的特點就是這個和一定比它的子序列中任何一個數要大,所以就有了判斷條件。

已知一序列:把數列第一個數存入dp[0],從第一個數開始遍歷,用一個dp陣列去存兩數之間的最大子序列和,因此得出動態轉移方程式dp[i]=max(dp[i-1]+a[i],a[i]);

程式碼實現:

#include <iostream>
#include 
<cstdio> using namespace std; int a[100001],dp[100001]; int main() { int T,n,i=0; scanf("%d",&T); while(T--) { scanf("%d",&n); for(int i=0;i<n;i++) { scanf("%d",&a[i]); } dp[0] = a[0]; int start = 0,end = 0,max = -1001;
int first = 0,last = 0; for(int i=0;i<n;i++) { if(dp[i-1]+a[i]>=a[i]) //判斷條件 { dp[i] = dp[i-1]+a[i]; end = i; } else//如果最長子序列和比a[i]還小,那麼就從當前a[i]開始重新遍歷 { dp[i] = a[i]; start
= end = i; } if(max<dp[i]) { max = dp[i]; first = start; last = end; } } printf("Case %d:\n%d %d %d\n",++i,max,first+1,last+1); if(T!=0) { printf("\n"); } } return 0; }

另一個改進的版本:

#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
    int t,n,a[100010],Case=1;
    int thissum,maxsum,begin,end,postion;
    cin>>t;
    while(t--){
        cin>>n;
        for(int i=0; i<n; i++)
            cin>>a[i];
        thissum=maxsum=a[0];
        begin=end=postion=0;
        for(int i=1; i<n; i++){
            if(thissum+a[i]<a[i]){//如對於6 -1 0 3 -4 3 2這組資料來說,就會更新postion
                thissum=a[i];
                postion=i;
            }
            else thissum+=a[i];
            if(thissum>maxsum){
                maxsum=thissum;
                begin=postion;
                end=i;
            }
        }
        printf("Case %d:\n%d %d %d\n",Case++,maxsum,begin+1,end+1);
    }
    return 0;
}