面试题14:剪绳子
1 题目
有一个长度为n的绳子,请把绳子剪成m段(m、n都是整数,n>1且m>1)每段绳子的长度记为k[0]、k[1]...k[m-1],求每一段相乘最大为多少?
2 思路
- 在剪第一刀的时候,我们有n-1种可能选择,分别是1,2,3,,n-1.因此f(n)=max(f(i)f(n-i))。
- 由于是自上而下递归,将会产生许多重复的子问题。为了避免重复计算。选择自下而上计算。
3 代码
int maxProductAfterCutting_solution(int length)
{
if (length<1)
return 0;
if(length<2)
return 1;
if(length<3)
return 2;
int *products = new int[length+1];
products[0]=0;
products[1]=1;
products[2]=2;
products[3]=3;
int max =0;
// 自下向上遍历,求各个长度为n的绳子的最佳间断策略
for(int i =4 ;i <=length;i++)
{
// 求长度为i时,最佳间断策略
max=0;
for(int j=0;j<=i/2;j++)
{
int product=products[j]*products[i-j];
if(product>max)
{
max=product;
}
}
products[i]=max;
}
max = products[length];
delete[] products;
return max;
}
数组中第i个元素表示把长度为i的绳子,剪成若干段后,各段乘机的最大值,即为f(i),所以上式代码中,数据长度为length+1,且第一个循环是“≤length”。
4 动态规划特点
- 是求解一个最优解
- 整体问题的最优解依赖于子问题的最优解
- 子问题之间还有相互重叠的更小的子问题。
- 由上往下分析,从下向上求解问题。