題目
思路
動態規劃
如果要求一個問題的最優解,而且該問題能分成若干個子問題,整體問題的最優解依賴於子問題的最優解,可以考慮用動態規劃解決。
動態規劃一般是自頂向下思考,自底向上實現的,爲什麼字底向上呢?因爲字底向上所消耗的內存空間少很多,爲了避免計算子問題時重複,可以將子問題的結果表記錄下來。
先自上而下分析,在長度爲n的繩子所求爲f(n),剪下一刀後剩下的兩段長度是i和n-i,在這個上面還可能繼續減(子問題),所以:
代碼
class Solution:
def solution1_DP(self,length):
if length < 2: # 因爲要求長度n>1,所以這裏返回0表示輸入非法
return 0
if length == 2:
return 1 # 長度爲2時,因爲要求剪下段數m>1,所以最大是1x1=1
if length ==3:
return 2 # 長度爲3時,因爲要求剪下段數m>1,所以最大是1x2=1
"""運行至此, 說明繩子的長度是 > 3的, 這之後當切割成0 / 1 / 2 / 3
這種子問題最大解就是其自身長度而不再需要考慮剪一刀的問題,
因爲它們剪一刀沒有不剪來的收益高,比如說,當繩子長度是4時,就有1*3,2*2兩種情況,而沒有必要說f(4) = f(1) * f(3) = 0*2 = 0。
而在當下這麼長的繩子上剪過纔可能生成0 / 1 / 2 / 3
這種長度的繩子, 它們不需要再減
所以下面的表中可以看到它們作爲子問題的值和上面實際返回的是不一樣的"""
max_len = 0
max_len_array = [0] * (length+1)
max_len_array[0] = 0
max_len_array[1] = 1
max_len_array[2] = 2
max_len_array[3] = 3
for i in range(4,length+1):
max_len = 0 # 每次將最大乘積清空,因爲要計算f(j)乘以f(i-j)的最大值,j超過i的一半時是重複計算,所以只需要考慮j不超過i的一半的情況
for j in range(1,i//2+1):
tmp = max_len_array[j] * max_len_array[i-j] # 計算f(j)*f(i-j)
if max_len < tmp:
max_len = tmp # 更新最大值
max_len_array[i] = max_len
return max_len
if __name__ == '__main__':
s = Solution()
print(s.solution1_DP(8))
運行結果: