剑指offer 14 剪绳子(动态规划和贪婪算法)

使用动态规划题的特征:

1、面试题通常是求一个问题的最优解(通常是求最大值或者最小值)

2、该问题可以分解成若干个子问题,并且子问题之间还有重叠的更小的子问题。

思路:

1、分析能否将大问题分解成小问题,且分解后的小问题也存在最优解

2、如果把小问题的最优解组合起来能够得到整个问题的最优解,则可以使用动态规划

题目:

给你一根长度为n的绳子,请把绳子剪成m段(m,n都是整数,m>1,n>1),每段绳子的长度记为k[0],k[1],k[2],,,,,k[m]。请问k[0]xk[1]xk[2]xk[3]xk[4],,,,,,,k[m]可能的最大乘积是多少?

例如,当绳子长度是8时,我们把它剪成长度分别为2,3,3的三段,此时得到的最大乘积是18。

思路:
状态转换方程:

f(n)=max( f[i] x f[n-i] )

当n很大时,只有当f[i]取最优解,并且f[n-i]也取最优解时,f[n]才是最优的。

举例子:

当n=1时,f(1)=0//因为不能剪了

当n=2时,f(2)=f(1)*f(1)=1//此时f(1)=1,而不是0

当n=3时,f(3)=max{ f(1)f(2), f(1)*f(1)*f(1)} =2

// 注意这里求f(1)*f(2)时,f(1)不能取0,因为此处它是作为长度为3时的内部最优解,此时f(1)=1

同样的f(2)不能取1,此时它作为长度为3时的内部最优解应该取2,因此,f(2)=2.

当n=4时,f(4)=max{f(1)*f(3),f(2)*f(2)}=4

//与上面一样,f(3)=3,f(2)=2

当n=5时,f(5)={f(1)f(4),f(2)f(3)}=6

总结:

从上面分析可知,当绳子长度为3时,f(3)=2, 而当f(3)作为内部最优解出现时,f(3)=3>2

而当绳子长度为4时,f(4)=4,而f(4)作为内部最优解出现时,f(4)=4=4

当绳子长度为5时,f(5)=6,而f(5)作为内部最优解出现时,f(5)=6>5

也就是说从n=4开始内部最优解取的是当绳子为n的时候的最优解,而不是n了。

因此动态规划要从n=4开始,而内部最优解的初始化要初始化到3才行。

 代码:

int maxProductAfterCutting_solution1(int length)

{

  if(length<2)

  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; //products[j]保存的就是内部最优解
 
 int result=0;

for(int i=4;i<=length;i++)

{

  result=0;

 for(int j=1;j<=i/2;j++)

 result=max(products[j]*products[i-j],result);

 }

 result=products[length];

 delete[]products;

 return result;

}




猜你喜欢

转载自blog.csdn.net/weixin_41413441/article/details/80697892