給出乙個整數序列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...