给你一根长度为n的绳子,请把绳子剪成m段 (m和n都是整数,n>1并且m>1)每段绳子的长度记为k[0],k[1],…,k[m].请问k[0]k[1]…*k[m]可能的最大乘积是多少?例如,当绳子的长度为8时,我们把它剪成长度分别为2,3,3的三段,此时得到的最大乘积是18。
首先定义函数F(n)表示吧长度为n的绳子剪成若干段后各段长度乘积的最大值。在剪第一刀的时候,我们有n-1种可能的选择,也就是剪出来的第一段的绳子可能长度为1,2,3,…,n-1,因此F(n)=max(F(i)*F(n-i)),其中0
这是一个从上到下的递归公式。由于递归会有很多重复的子问题,从而会有大量不必要的重复运算。为了避免上述问题,我们不采用递归,从下而上来顺序计算,即先计算F(1)接着计算F(2)…直到得到F(n)。
当绳子长度为2时,只能剪成两段长度都为1的,因此f(2)=11=1,当绳子长度为3的时候可以剪成长度分别为1、2的两段或者长度都为1的三段,因为111=1<12=2因此f(3)=2
public static int maxProductAfterCutting_solution1(int length)
{
//对长度为0、1、2、3的绳子进行特殊处理
if(length<2)
{
return 0;
}
if(length==2)
{
return 1;
}
if(length==3)
{
return 2;
}
//products数组第i个元素代表着长度为i的绳子剪成若干段之后各段长度乘积的最大值
//i>=4时上述概念有效
int[] products=new int[length+1];
//下面的初始化不代表着最大值,是为了方便i>=4的计算
products[0]=0;
products[1]=1;
products[2]=2;
products[3]=3;
int max=0;
for(int i=4;i<=length;i++)
{
max=0;
//寻找长度为i的绳子剪成若干段之后各段长度乘积的最大值
for(int j=1;j<=i/2;j++)
{
int product=products[j]*products[i-j];
if(max<product)
{
max=product;
}
}
products[i]=max;
}
max=products[length];
return max;
}