動態規劃經典問題 最大連續子串行和

2021-10-22 12:02:37 字數 4216 閱讀 7639

給出乙個整數序列s,其中有n個數,定義其中乙個非空連續子串行t中所有數的和為t的「序列和」。 對於s的所有非空連續子串行t,求最大的序列和。 變數條件:n為正整數,n≤1000000,結果序列和在範圍(-263,263-1)以內。

輸入描述:

第一行為乙個正整數n,第二行為n個整數,表示序列中的數。

輸出描述:

輸入可能包括多組資料,對於每一組輸入資料,

僅輸出乙個數,表示最大序列和。

示例1輸入

51 5 -3 2 4

61 -2 3 4 -10 6

4-3 -1 -2 -5輸出9

7-1例如給定乙個序列a1a2…an 例如1,-2,3,4,-10,6。目標是找到乙個連續的子串行ai到aj使得ai+…+aj最大。那麼該例子的最大連續子串行就是3,4,它的和為7。

如果直接來考察這個問題是非常難求解的,這是因為連續子串行的兩端都是變化的。所以我們自然而然可以想到,將一端固定下來。例如我們可以考慮某乙個元素aj為末尾元素的情況下,其最大連續子串行的和。表示為…+aj。那麼…+aj就有兩種情況,一種是最大連續子串行只有乙個元素aj,例如上面例子的1,3,6。那麼另外一種情況就是最大的連續子串行有多個元素即…+aj-1+aj。假設將以aj為末尾元素的最大連續子串行和為f(j)。那麼對於上面兩種情況就可以寫成f(j) = aj或者f(j) = f(j-1) + aj。所以得到f(j) = max。要麼我們要求解該問題,只需依次的從小到大獲取所有的f(j),然後從中找到最大的即為最大連續子串行和。

#include

#include

#include

#include

using

namespace std;

const

int maxn =

1e6+10;

const

int inf = int_max;

long

long arr[maxn]

;//func(n)為以an為末尾元素的最大連續子串行和

long

long

func

(int n)

else

return answer;

}int

main()

long

long maxnum =

-inf;

for(

int i=

0;i)printf

("%lld\n"

,maxnum);}

return0;

}

這樣用遞迴寫雖然可以得到正確答案,但是一般都會超時,因為它的複雜度是n的平方的。而之所以會這麼高,是因為在遞迴中產生了很多相同的子問題,而每次遇到這種子問題我們都要重新計算一次,造成時間浪費,所以複雜度高。

有了上面的分析,我們自然而然可以想到建立乙個備忘錄陣列,將子問題的解存到備忘錄裡。如果下次又需要求解這個子問題的值,就可以在常數的時間內從備忘錄裡將這個子問題的值給取出來,而不是重新計算,這就大大的減少了時間複雜度。這就是遞迴策略+記憶化。其實,動態規劃可以理解為加上了備忘錄的遞迴演算法。為什麼是自頂向下呢?比如f(n) = max,我們要求f(n),需要求出f(n-1)。要求f(n-1),需要求f(n-2)…以此類推,這不就是自頂向下嗎。

#include

#include

#include

#include

using

namespace std;

const

int maxn =

1e6+10;

const

int inf = int_max;

long

long arr[maxn]

;//func(n)為以an為末尾元素的最大連續子串行和

long

long

func

(int n)

else

return answer;

}long

long memo[maxn]

;//備忘錄

long

long

func1

(int n)

long

long answer;

if(n ==0)

else

memo[n]

= answer;

//將f(n)放入備忘錄

return answer;

}int

main()

// long long maxnum = -inf;

// for(int i=0;i

// maxnum = max(maxnum,func(i));

// }

// printf("%lld\n",maxnum);

fill

(memo,memo+n,-1

);//初始化備忘錄所有元素為-1

long

long maxnum =

-inf;

for(

int i=

0;i)printf

("%lld\n"

,maxnum);}

return0;

}

這就相當於f(0)到f(n-1)每個都只計算了一次,不存在重複計算,那麼時間複雜度就降低到了o(n)

既然可以用遞迴的方法解決,那麼就可以轉化為遞推的方法解決。

#include

#include

#include

#include

using

namespace std;

const

int maxn =

1e6+10;

const

int inf = int_max;

long

long arr[maxn]

;//func(n)為以an為末尾元素的最大連續子串行和

//樸素遞迴

long

long

func

(int n)

else

return answer;

}//自頂向下備忘錄法

long

long memo[maxn]

;//備忘錄

long

long

func1

(int n)

long

long answer;

if(n ==0)

else

memo[n]

= answer;

//將f(n)放入備忘錄

return answer;

}//自底向上的遞推

long

long dp[maxn]

;//記錄f(i)的值

void

func3

(int n)

else

dp[i]

= answer;

}return;}

intmain()

// long long maxnum = -inf;

// for(int i=0;i

// maxnum = max(maxnum,func(i));

// }

// printf("%lld\n",maxnum);

// fill(memo,memo+n,-1); //初始化備忘錄所有元素為-1

// long long maxnum = -inf;

// for(int i=0;i

// maxnum = max(maxnum,func1(i));

// }

// printf("%lld\n",maxnum);

fill

(dp,dp+n,-1

);//初始化備忘錄所有元素為-1

long

long maxnum =

-inf;

func3

(n);

for(

int i=

0;i)printf

("%lld\n"

,maxnum);}

return0;

}

看完之後,有沒有讓你更加理解動態規劃呢?

最大連續子串行和 動態規劃經典題目

題目 給定k個整數的序列,其任意連續子串行可表示為,其中 1 i j k。最大連續子串行是所有連續子序中元素和最大的乙個,例如給定序列,其最大連續子串行為,最大連續子串行和即為20。注 為方便起見,如果所有整數均為負數,則最大子串行和為0。解決這樣乙個問題是乙個很有趣的過程,我們可以嘗試著從複雜度比...

最大連續子串行之和(動態規劃)

1.問題描述 設n個元素的序列儲存在陣列a 0.n 1 中,求陣列中連續子串行之和的最大值。2.遞推公式 設all i 為子問題a i.n 1 的連續子串行之和的最大值,start i 為從a i 開始的連續序列之和的最大值,因此 all i a n 1 i n 1時,all i maxi 0,1,...

動態規劃 最大連續子串行乘積

題目描述 給定乙個浮點數序列 可能有正數 0和負數 求出乙個最大的連續子串行乘積。分析 若暴力求解,需要o n 3 時間,太低效,故使用動態規劃。設data i 第i個資料,dp i 以第i個數結尾的連續子串行最大乘積,若題目要求的是最大連續子串行和,則易確定狀態轉移方程為 dp i max dat...