1. 程式人生 > >【程式設計網格無水題】【動態規劃篇】之【最大字串和】

【程式設計網格無水題】【動態規劃篇】之【最大字串和】

Written By MorrowWind,csdnicewing

可以到洛谷的P115上去練習  https://www.luogu.org/problemnew/show/P1115

題目描述

        給出資料個數n和一段序列,選出其中連續且非空的一段使得這段和最大。

輸入資料:共兩行,第一行是資料個數n,第二行是序列

輸出資料:共一行,一個數:最大的和

樣例輸入

        7
        2 -4 3 -1 2 -4 3

樣例輸出

       4

解釋:3 -1 2即為子段

資料範圍:n<=200000

看資料規模,複雜度最大不能超過nlogn,應該有O(n)的做法,下面給出O(n)的做法

觀察問題,發現有很強的階段性。

設num[i]為資料集(從0開始存),dp[i]的含義為以第i個元素結尾的子段的最大子段和,它就是階段。由於這個子段和只能與第(i-1)個元素結尾的子段和有關係,所以容易知道轉移方程為


 dp[i]=num[0]                            (i==0)
       =max(num[i],dp[i]+num[i]) (i>n)


即如果第i個元素如果接到前面的字串上不如自己自成一串,那就自成一串,否則加到前面上面去。
最後答案就是dp[i]中的最大值。


下面上程式碼:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<climits>
using namespace std;
int n,ans;
int num[200010];
int dp[200010];


int main(){
    scanf("%d",&n);
    for(int i=0;i<n;i++)
        scanf("%d",&num[i]);
    dp[0]=num[0];
    for(int i=1;i<n;i++)
        dp[i]=max(num[i],num[i]+dp[i-1]);
    ans=-INT_MAX;
    for(int i=0;i<n;i++)
        ans=max(ans,dp[i]);
    printf("%d",ans);
    return 0;
}

祝大家期末考試順利!

(黃老仙說這麼晚還看我直播,你一定考不好)