標籤:blog http os io 使用 ar for 2014 問題
問題描述:
給定一個整數序列, 序列中可能有負數。 目的是找出這個序列的連續子序列(即子序列的元素的選取是連續的從序列中選取的)。即通過確定i, j 的值, 使得的值達到最大。 我們定義, 當所有的元素為負數值的時候, 那麼maximum subsequence sum 為0。
下面我們用動態規劃的技術去求解。
為了找到最大連續子序列和, 不難看出, 在擴充我們的求和視窗的時候, 當新加進視窗的元素市負數的時候, 只要我們得到的新的求和視窗的值求和不是負數, 那麼我們就不能丟掉這個新的負數。 也就是我們就不應該去重新的從新元素的下個元素開始重新開闢新的視窗(如果是這種情況, 我們的舊的視窗的求和的最大值已經被儲存下來)。 之所以如此是因為只要我們的求和視窗是真的, 我們就有理由期望後面的元素的假如會得到更大的maximum subsequence sum。
我們知道, 能夠使用動態規划去求解的問題滿足兩個原則。 一個是這個問題必須具有最優子結構(optimal substructure), 這個性質說的是可以通過求解子問題的最優解, 然後combine 稱為我們的optimal solution。
第二個性質是遞迴(recursion), 或者也可以說成是重疊子問題(overlapping subproblem)。
動態規划算法的實現主要有兩種方式, 一種是bottom-up, 一種是top-down。
下面我們介紹的是bottom-up 實現動態規劃。
具體步驟如下:
記S[i] 為maximum subsequence sum till i-th element。
公式如下:
由上面的公式可知, S[i]取的是要麼是A[i], 要麼是i-1(包含)前面的maximum susequence sum 和A[i] 之和。 我們可以通過判斷S[i-1] 是否小於0來做出判斷是否需要重新開闢從A[i] 為起點的新的視窗。
舉個例子, 假如序列為-2, -3, 4, -1, -2, 1, 5, -3 如下:
所以, 最終我們找到這個序列的maximum subsequence 為7。
#include <iostream>#include <vector>using namespace std;int maxSubSum(const vector<int> &a) { int maxSum = 0; int thisSum = 0; for (int j = 0; j < static_cast<int>(a.size()); j++) { thisSum += a[j]; if(thisSum > maxSum) { maxSum = thisSum; } else if(thisSum < 0) { // eliminate negative prefix thisSum = 0; } } return maxSum;}int main(){ vector<int> myArr = {-2, -3, 4, -1, -2, 1, 5, -3}; cout << maxSubSum(myArr) << endl; return 0;}
演算法分析如下:時間複雜度為O(N)。空間複雜去為O(1).
運行結果為:
dynamic programming 之Maximum Sub-Sequence Sum(最大子序列和問題)