题目如下:
给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m、n都是整数,n>1并且m>1),每段绳子的长度记为 k[0],k[1]…k[m-1] 。请问 k[0]k[1]…*k[m-1] 可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
示例 1:
输入: 2
输出: 1
解释: 2 = 1 + 1, 1 × 1 = 1
示例 2:
输入: 10
输出: 36
解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36
解题方法(一)
当n>=5时,3 ( n − 3 ) > = 2 ( n − 2 ) 且只在n取5时取等号,且它们都大于n ,所以应把绳子剪成尽量多的3
书上言尽于此,我想了下如果剪成其它大小的会不会更好。如果剪成4,那么4 = 2 × 2 = 2 + 2 就还是和剪成两个2一样,如果剪成5,那么5还能继续剪剪成3和2,往后也是一样。试想更大的数,比如15,得到一段15以后不剪是不可能的,因为前面说了这时候3 ( n − 3 ) > 2 ( n − 2 ) > n ,那么剪成更小的段,只要不小于5就一定满足这个就要继续减,如果比5小,从1~4的情况都想过了,4是不用管的或者剪成两个2,3就保留,2也保留,1不要出现。
当0< number <=3的时候,我们知道最大乘积就是number-1
当number=4,return number * max,4 *1=4;
当number>4时,我们得出规律,尽可能多剪长度为3的绳子,最后的乘积是最大的。
贪心算法思想
代码如下:
#include<stdio.h>
int cutRope(int number)
{
int max = 1;
if (number <= 3 && number > 0)
{
return number - 1;
}
while (number > 4)
{
number -= 3;
max *= 3;
}
return number * max;
}
int main()
{
int a=0;
scanf("%d",&a);
printf("%d\n",cutRope(a));
return 0;
}运行截图如下:

解题方法(二)
动态规划算法
首先定义函数f(n)为把长度为n的绳子剪成若干段后各段长度乘积的最大值。在剪第一刀时,我们有n-1种选择,也就是说第一段绳子的可能长度分别为1,2,3…,n-1。因此f(n)=max(f(i)*f(n-i)),其中0<i<n。这是一个自上而下的递归公式。由于递归会有大量的不必要的重复计算。
一个更好的办法是按照从下而上的顺序计算,也就是说我们先得到f(2),f(3),再得到f(4),f(5),直到得到f(n)。当绳子的长度为2的时候,只能剪成长度为1的两段,所以f(2) = 1,当n = 3时,容易得出f(3) = 2。
代码如下:
int maxProductOfCutRope(int length)
{
if(length < 2)
return 0;
if(length == 2)
return 1;
if(length == 3)
return 2;
vector<int> products{0, 1, 2, 3};
for(int i = 4; i <= length; ++i)
{
int max = 0;
for(int j = 1; j <= i/2; ++j)
{
int product = products[j] * products[i - j];
if(max < product)
{
max = product;
}
}
products.push_back(max);
}
return products[length];
}
















