题目
思路
动态规划
如果要求一个问题的最优解,而且该问题能分成若干个子问题,整体问题的最优解依赖于子问题的最优解,可以考虑用动态规划解决。
动态规划一般是自顶向下思考,自底向上实现的,为什么字底向上呢?因为字底向上所消耗的内存空间少很多,为了避免计算子问题时重复,可以将子问题的结果表记录下来。
先自上而下分析,在长度为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))
运行结果: