动态规划
求一个问题的最优解(通常是求最大值或者最小值),而且该问题能够分解成若干个子问题,并且子问题之间还有重叠的更小的子问题,考虑用动态规划来解决。整体问题的最优解是依赖各个子问题的最优解。
在应用动态规划之前要分析能否把大问题分解成小问题,分解后的每个小问题也存在最优解。如果把小问题的最优解组合起来能够得到整个问题的最优解,那么可应用动态规划解决这个问题。
剪绳子(动态规划)
题目:给你一根长度为n的绳子,请把绳子剪成整数长的m段(m、n都是整数,n>1并且m>1,m<=n),每段绳子的长度记为k[1],…,k[m]。请问k[1]x…xk[m]可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。(O(n2)时间和O(n)空间)(2<=n<=60)
注:在应用动态规划时,每一步都可能面临若干个选择。由于事先不知剪在哪个位置是最优的解法,只好把所有的可能都尝试一遍,然后比较得出最优的解法。f(n) = max(f(i) * f(n-i)),其中0<i<n.
int cutRope(int number) {
if(number < 2)
return 0;
if(number == 2)
return 1;
if(number == 3)
return 2;
int* products = new int[number+1];
products[0] = 1;
products[1] = 1;
products[2] = 2;
products[3] = 3;
int max = 0;
for(int i = 4;i <= number;++i) {
max = 0;
for(int j = 1;j <= i/2;++j) {
int product = products[j] * products[i-j];
if(max < product)
max = product;
products[i] = max;
}
}
max = products[number];
delete[] products;
return max;
}
贪心算法(需数学功底)
当应用贪心时,每一步都可以做出一个贪婪的选择,基于这个选择,确认能够得到最优解。需要用数学方式来证明贪婪选择是正确的。
int cutRope(int number) {
if(number < 2)
return 0;
if(number == 2)
return 1;
if(number == 3)
return 2;
//尽可能多地剪去长度为3的线段
Int timesOf3 =number/3;
//当绳子最后剩下长度为4时,不能再剪去长度为3的绳段
//此时更好的方法是把绳子剪成长度为2的两段,因为2*2 > 3*1
if(number – timesOf3 *3 == 1)
timesOf3 -= 1;
int timesOf2 = (number – timesOf3 * 3) / 2;
return (int)(pow(3,timesOf3))*(int)(pow(2,timesOf2));
}
测试用例
功能测试(长度大于5)
边界值测试(0,1,2,3,4)