题目描述
给你一根长度为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。
考察点:动态规划或者贪心;
思路:动态规划的思路是自上而分析问题,自下而上解决问题。贪心是灵活运用公式推导。
解法1:动态规划。方程为F(n)=F(i)*F(n-i);
class Solution {
public:
int cutRope(int number) {
if (number < 2)
return 0;
if (number == 2)
return 1;
if (number == 3) //题目要求必须剪一刀,所以有这些初始值
return 2;
vector<int> products(number + 1);//暂存每个最优剪绳子方案
products[0] = 0;
products[1] = 1;
products[2] = 2;
products[3] = 3;//初始的分段代价。既然可以分割,所以有了很多可能。
int max; //存放最大值的整型
for (int i = 4; i <= number; i++)
{
max = 0;
for (int j = 0; j <= i / 2; j++) //切割问题切到一半即可涵盖全部情况。
{
int product = products[j] * products[i - j];//以j为界进行分割
if (max < product)
max = product;
products[i] = max;//取最大值作为代价最大。
}
}
max = products[number];
return max;
}
};
解法2:贪心(需要用数学归纳法证明,尽可能的将绳子剪成3的乘积最大,当剩下的一段为4时,就剪成2,乘积最大。)
class Solution {
public:
int cutRope(int number) {
if (number < 2)
return 0;
if (number == 2)
return 1;
if (number == 3)
return 2;
int numOf3 = number / 3;
if (number - 3 * numOf3 == 1)//剩下的一段为4
numOf3 -= 1;//剪为3的数量减少1,剩下的剪成2
int numOf2 = (number - 3 * numOf3)/2;
return (int)(pow(3, numOf3)) * (int)(pow(2, numOf2));//乘法输出乘积
}
};