题目描述
给你一根长度为n的绳子,请把绳子剪成整数长的m段(m、n都是整数,n>1并且m>1),每段绳子的长度记为k[0],k[1],…,k[m]。请问k[0]xk[1]x…xk[m]可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
输入描述:
输入一个数n,意义见题面。(2 <= n <= 60)
输出描述:
输出答案。
示例1
输入
8
输出
18
链接:https://www.nowcoder.com/questionTerminal/57d85990ba5b440ab888fc72b0751bf8?answerType=1&f=discussion
来源:牛客网
递归
我们先定义函数f(n)为把绳子剪成若干段之后的各段长度乘积的最大值.在剪第一刀的时候,我们会有n-1种可能的选择,也就是说剪出来的第一段绳子的长度可能为1,2,…n-1.因此就有了递归公式 f(n) = max(f(i)*f(n-i)),其中0<i<n.
class Solution:
def cutRope(self, number):
# write code here
if number<2:
return 0
if number==2:
return 1
if number==3:
return 2
return self.cut(number)
def cut(self,number):
if number<5:
return number
maxi = 0
for i in range(1,number/2+1):
maxi = max(self.cut(i)*self.cut(number-i),maxi)
return maxi
链接:https://www.nowcoder.com/questionTerminal/57d85990ba5b440ab888fc72b0751bf8?answerType=1&f=discussion
来源:牛客网
动态规划
首先定义函数f(n)为把长度为n的绳子剪成若干段后各段长度乘积的最大值。在剪第一刀的时候,我们有n-1种可能的选择,也就是剪出来的第一段绳子的可能长度为1,2,…n-1。因此f(n)=max(f(i)xf(n-i)),其中0<i<n.
这是一个从上至下的递归公式。由于递归会有很多重复的子问题,从而有大量不必要的重复计算。一个更好的办法是按照从下而上的顺序计算,也就是说我们先得到f(2)、f(3),再得到f(4)、f(5),直到得到f(n)。
当绳子的长度为2时,只可能剪成长度为1的两段,因此f(2)等于1.当绳子的长度为3时,可能把绳子剪成长度为1和2的两段或者长度都为1的三段,由于1x2>1x1x1,因此f(3)=2
也就是先计算f(1)、f(2)、f(3)…的值,大的值等于小的值的乘积
在代码中,子问题的最优解存储在数组array里。数组中第i个元素表示把长度为i的绳子剪成若干段之后各段长度乘积的最大值,即f(i)。我们注意到代码中的第一个for循环变量i是顺序递增的,这意味着计算顺序是自下而上的。因此,在求f(i)之前,对于每一个j(0<i<j)而言,f(j)都已经求解出来了,并且结果保存在array[j]里,为了求解f(i),我们需要求出所有可能的f(j)xf(i-j)并比较得出它们的最大值。这就是代码中第二个for循环的功能。
# -*- coding:utf-8 -*-
class Solution:
def cutRope(self, number):
# write code here
if number<2:
return 0
if number==2:
return 1
if number==3:
return 2
array = [0]*(number+1)
array[0] = 0
array[1] = 1
array[2] = 2
array[3] = 3
for i in range(4,number+1):
maxi = 0
for j in range(1,i/2+1):
maxi = max(array[j]*array[i-j],maxi)
array[i] = maxi
return array[number]
数学
绳子长度为n,分成m分,那先设每分长度为x, 分数m=n/x 那么结果就是 n/x个 x 相乘 f(x)=x^(n/x) 求导:如下图
链接:https://www.nowcoder.com/questionTerminal/57d85990ba5b440ab888fc72b0751bf8?answerType=1&f=discussion
来源:牛客网
所以问题就回到了n/3的个数上面
当n能被3整除的时候,乘积=n^(n/3)
当n除3余1的时候,这时候发现多了一个1,这个1是不是很鸡肋,但是把前面的一个3拿出来,把这个一个1和前面一个3 分解为2和2,就变大了,所以乘积为 3^(n/3 - 1) * 4
当n除3余2的时候,乘积为n^(n/3) * 2
# -*- coding:utf-8 -*-
class Solution:
def cutRope(self, number):
# write code here
if number<2:
return 0
if number==2:
return 1
if number==3:
return 2
tmp = number%3
result = 0
if tmp==0:
result = pow(3,number/3)
if tmp==1:
result = pow(3,number/3-1)*4
if tmp==2:
result = pow(3,number/3)*2
return result