给你一根长度为 n 绳子,请把绳子剪成 m 段(m、n 都是整数,2≤n≤58 并且 m≥2)。
每段的绳子的长度记为k[0]、k[1]、……、k[m]。k[0]k[1] … k[m] 可能的最大乘积是多少?
例如当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到最大的乘积18。
一 用动态规划
通常是用来求最优解(最大值,最小值)
从上到下分析, 从下到上实现
什么时候可以用动态规划:
(1)大问题分解为小问题,如果小问题的最优解组合起来 ==大问题的最优解
(2)整体问题的最优解依赖于各个子问题的最优解
(3)大问题分解为小问题,这些小问题还有相互重叠的更小子问题(之前的青蛙)
java:
class Solution {
public int maxProductAfterCutting(int length)
{
int n=length;
if(n<2)
return 0;
if(n==2)
return 1;
if(n==3)
return 2;
int[] p = new int[n+1];
p[0]=0;
p[1]=1;
p[2]=2;
p[3]=3;
int max=0;
int pro=0;
for(int i = 4;i<=n;i++){
max=0;
for(int j =1;j<=i/2;j++){
pro=p[j]*p[i-j];
if(max < pro)
max = pro;
p[i] = max;
}
}
max = p[n];
return max;
}
}
C++:
class Solution {
public:
int maxProductAfterCutting(int length) {
if(length <2)
return 0;
if(length==2)
return 1;
if(length==3)
return 2;
int *p = new int[length+1];
p[0]=0;
p[1]=1;
p[2]=2;
p[3]=3;
int max=0;
int pro=0;
for(int i=4;i<=length;i++){
max = 0; //新的 i 重新开始 算max
for(int j=1;j<=i/2;j++){
pro = p[j]*p[i-j];
if(max < pro)
max = pro;
p[i] =max;
}
}
max = p[length];
delete[] p;
return max;
}
};
二 用贪心算法:
在每一步都做出贪婪选择,为什么这样的贪婪选择会得到最优解,需要用数学方式证明贪婪选择是正确的。
java:
class Solution {
public int maxProductAfterCutting(int length)
{
int n=length;
if(n<2)
return 0;
if(n==2)
return 1;
if(n==3)
return 2;
int obj3= n-((n/3)*3)==1? n/3-1 : n/3;
int obj2 = (n-obj3*3)/2;
return (int)Math.pow(3,obj3) * (int)Math.pow(2,obj2);
}
}
C++:
class Solution {
public:
int maxProductAfterCutting(int length) {
int n=length;
if(n<2)
return 0;
if(n==2)
return 1;
if(n==3)
return 2;
int obj3=n/3;
if((n-obj3*3)==1) //最后的余数要是4的话,最优解是2*2=4 > 1*3=3
--obj3; //所以得把最后的那个3 变成 4
int obj2=(n-obj3*3)/2;
return (int)(pow(3,obj3)) * (int)(pow(2,obj2));
}
};