题目:给你一段长度为n的绳子,请将绳子剪成m段(m、n都是大于1的正整数),每段绳子的长度记为k[0]/k[1]/······k[m],求各段绳子最大乘积为多少?当绳子的长度为8,剪成2/3/3三段,最大乘积为18。根据数学原理,k[1]+k[2]+······=m,为定值,要想让乘积最大,需要每段绳子长度尽可能靠近。在剪第一刀时,可以有n-1种选择,假设剪到了长度为i的位置,我们想要整个问题的最优解,需要同样优化的方法将长度为i、n-i的绳子也剪成最优化,整体问题的最优解依赖于各个子问题的最优解。f(n)=max(f(i)*f(n-i)),采用自下而上的顺序动态规划,f(2)=1 f(3)=2 f(4)=4 f(5)=6
例如长度为8时,第一刀剪出的第一段可能为1——7,当剪成2/6时,还有一刀,选择6,为使最终乘积最大,需要6同样的方法剪得最优。
# -*- coding:utf-8 -*-
class Solution:
def MaxProductAfterCut(self, n):
# 动态规划
if n<2:
return 0
if n==2:
return 1
if n==3:
return 2
products=[0]*(n+1)
products[0]=0
products[1]=1
products[2]=2
products[3]=3
for i in range(4,n+1):
max=0
for j in range(1,i//2+1):
product=products[j]*products[i-j]
if product>max:
max=product
products[i]=max
#print(products)
return products[n]
def MaxProductAfterCut2(self, n):
# 贪婪算法
if n < 2:
return 0
if n==2:
return 1
if n==3:
return 2
timesOf3 = n//3
if n - timesOf3*3 == 1:
timesOf3 -= 1
timesOf2 = (n - timesOf3 * 3)//2
return (3**timesOf3) * (2**timesOf2)
if __name__=="__main__":
print(Solution().MaxProductAfterCut(8))
print(Solution().MaxProductAfterCut(10))
#print(Solution().NumberOf1(0))
print(Solution().MaxProductAfterCut2(8))
print(Solution().MaxProductAfterCut2(10))