最大子序列和問題
最大子序列和問題(Maximum Subsequence Problem)是一個著名的動態規劃問題,它的目標是在一個給定的序列中找到一個子序列,其和最大。這裡的「子序列」是指原始序列中的一些元素,它們保持原始的相鄰關係。例如,在序列 [2, 1, -3, 4, 2]
中,子序列 [2, 1, 4, 2]
是一個合法的子序列,而 [2, 4, 2]
則不是,因為中間的 1
元素沒有被包含。
解決這個問題的動態規劃算法如下:
- 設
f[i]
表示以a[i]
為最後一個元素的最長子序列和,那麼f[i] = max(f[i-1], 0) + a[i]
。 - 如果
f[i-1] >= 0
,那麼f[i] = f[i-1] + a[i]
,因為我們可以在上一個子序列後面加上a[i]
得到一個更大的和。 - 如果
f[i-1] < 0
,那麼f[i] = 0 + a[i] = a[i]
,因為上一個子序列和為負,我們可以捨棄它,從a[i]
開始構建一個新的子序列。
這樣,我們就可以通過累加的方式來計算每一個位置 i
的最大子序列和。時間複雜度為 O(n)
,空間複雜度也是 O(n)
,因為我們需要存儲 f[i]
的值。
以下是一個簡單的Python實現:
def max_subsequence_sum(arr):
n = len(arr)
dp = [0] * n # 動態規劃狀態
for i in range(n):
if dp[i-1] >= 0:
dp[i] = dp[i-1] + arr[i]
else:
dp[i] = arr[i]
# 最後一個元素總是最後一個子序列的結束
dp[-1] += dp[-2]
# 找到最大子序列和
max_sum = dp[0]
for i in dp:
max_sum = max(max_sum, i)
return max_sum
# 測試
arr = [2, 1, -3, 4, 2]
print(max_subsequence_sum(arr)) # 輸出應該是6
這個算法不僅可以找到最大子序列和,還可以找到相應的子序列。只需要在計算過程中記錄每一個 f[i]
的來源位置,就可以在最後回溯得到最大子序列。