要求:剪绳子
给你一根长度为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。
测试用例:
- 功能测试(绳子的初始长度大于5)
- 边界值测试(绳子的初始长度分别为0,1,2,3,4)
本题考点:
- 考查应聘者的抽象建模能力。应聘者需要把一个具体的场景抽象成一个能够用动态规划或者贪婪算法解决的模型。
- 考查应聘者对动态规划和贪婪算法的理解。能够灵活运用动态规划解决问题的关键是具备从上到下分析问题、从下到上解决问题的能力,而灵活运用贪婪算法则需要扎实的数据基本功。
源代码:
#include <cmath>
//动态规划
int maxProductAfterCuttig_solution(int length)
{
if (length < 2)
return 0;
if (length == 2)
return 1;
if (length == 3)
return 2;
int *product = new int[length + 1];
product[0] = 0;
product[1] = 1;
product[2] = 2;
product[3] = 3;
//这里的是错误的,我误以为
//当n大于3最大值f(n) = f(n/2)*f(n - n/2)
/*int max = 0;
int midPos = 0;
int upPos = 0;
for (int i = 4; i <= length; i++)
{
max = 0;
midPos = i / 2;
upPos = i - midPos;
product[i] = product[midPos] * product[upPos];
}*/
//正确的方法如下,最大值f(n) = max(f(i) *f(n-i))
int max = 0;
for (int i = 4; i <= length; i++)
{
max = 0;
int tempValue = 0;
for (int j = 0; j <= i / 2; ++j)
{
tempValue = product[j] * product[i - j];
if (max < tempValue)
max = tempValue;
product[i] = max;
}
}
max = product[length];
delete[]product;
return max;
}
//贪婪算法
int maxProductAfterCutting_solution2(int length)
{
if (length < 2)
return 0;
if (length == 2)
return 1;
if (length == 3)
return 2;
//尽可能多地剪去长度为3的绳子段
int timesOf3 = length / 3;
if (length - timesOf3 * 3 == 1)
timesOf3 -= 1;
int timesOf2 = (length - timesOf3 * 3) / 2;
return pow(3, timesOf3) *pow(2, timesOf2);
}
参考代码:https://github.com/zhedahht/CodingInterviewChinese2/tree/master/14_CuttingRope
自己代码:https://github.com/quinta2019/Offer/tree/master/14_Q_CuttingRope