問題來自《程式設計珠璣》這本書,我記得以前考研的時候模擬題目中也有過類似的題目,當時書上的**特別簡單易懂,不過也有些時日了,當時是怎樣寫的基本也就忘了。
現在回過頭來在看看這個問題。 1.
問題描述
問題來自一維的模式識別,問題的輸入是具有n個浮點數的向量x,輸出是輸入向量的任何連續子向量的最大和。例如,如果輸入向量包含下面10個元素:31
-41 59
26 -53 58
97 -93
-23 84
那麼該程式的輸出為x[2..6]的總和,即187。當所有數都是正數時,問題很容易解決,此時最大的子向量就是整個輸入向量。當輸入中含有負數時麻煩就來了:是否應該包含某個負數並期望旁邊的整數會彌補它呢?
2.簡單演算法
完成該任務的淺顯程式就是對所有滿足0<=i<=j的(i,j)整數對進行迭代。對每個整數對,程式都要計算x[i,j]的總和,並檢驗總和是否大於迄今為止的最大總和。該演算法的偽**如下所示:
maxsofar = 0
fori = [0,n)
for j = [i,n)
sum = 0
for k = [i,j]
sum += x[k]
/* sum is sum of x[i..j] */
maxsofar = max(maxsofar, sum)
這段**簡潔、直觀並且易於理解。不幸的是,程式的執行速度也很慢。 3.
兩個平方演算法
有兩個演算法可以明顯地提高第乙個演算法的速度,其中乙個是比較明顯可想的,而另外乙個則不那麼明顯,它們的時間複雜度都是平方時間(對於輸入規模n來說,需要執行o
(n^2
)步)。
可以注意到,x[i..j]的總和與前面已計算出的總和(x[i..j-1]的總和)密切相關。利用這一關係即可得到演算法。偽碼如下:
maxsofar = 0
fori = [0,n)
sum = 0
for j = [i,n)
sum += x[j]
/* sum is sum of x[i..j] */
maxsofar = max(maxsofar, sum)
另乙個平方演算法是通過訪問在外迴圈執行之前就已構建的資料結構的方式在內迴圈中計算總和。cumarr中的第i個元素包含x[0..i]中各個數的累加和,所以x[i..j]中各個數的總和可以通過計算cumarr[j]-cumarr[i-1]得到。從而得到如下所示的偽碼:
cumarr[-1] = 0
fori = [0,n)
cumarr[i] = cumarr[i-1] + x[i]
maxsofar = 0
fori = [0,n)
for j = [i,n)
sum = cumarr[j] - cumarr[i-1]
/* sum is sum of x[i..j] */
maxsofar = max(maxsofar, sum)
下面開始貼上** 動態規劃演算法:
#include#includeusing namespace std;
int findmax(int a,int n)
return sum;
} int main()
; cout<
最大子向量和(連續子陣列的最大和)
題目1372 最大子向量和 連續子陣列的最大和 時間限制 1 秒 記憶體限制 32 兆 特殊判題 否 提交 2132 解決 556 題目描述 hz 偶爾會拿些專業問題來忽悠那些非計算機專業的同學。今天 jobdu 測試組開完會後 他又發話了 在古老的一維模式識別中 常常需要計算連續子向量的最大和 當...
求連續序列的最大子串行和
求乙個序列的最大子串行和,這個可以有幾種方法都可以去求解,這裡我提供兩種方法給大家。假如這個序列是,顯然最大子串行和是7,那麼這個要怎麼去計算呢?第一種方法就是順序求取,可以先算一下只有乙個元素的最大值是多少,再算一下連續兩個元素的最大值是多少,再算一下連續三個元素的最大值是多少 直到n個元素全部都...
求最大子列和問題
給定k個整數組成的序列,連續子列 被定義為,其中 1 i j k。最大子列和 則被定義為所有連續子列元素的和中最大者。例如給定序列,其連續子列有最大的和20。在此方法中用了三個迴圈,第一層是子列左端,第二層是子列右端,裡層為子列的求和。t n o n 3 int thissum maxsum 0 i...