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;
}