题目描述
给你一根长度为n的绳子,请把绳子剪成m段(m、n都是整数,n>1并且m>1),每段绳子的长度记为k[0],k[1],…,k[m]。请问k[0]xk[1]x…xk[m]可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
这里分别使用动态规划和贪心算法
动态规划:对于给定长度 n 的绳子, f ( n ) = max ( f ( i ) * f ( n - i ) )。然后我们从下往上进行计算。
贪婪算法:首先我们需要证明的,当 n >= 6的时候,我们尽可能多的剪出来长度为 3 的绳子,这种思路是正确的。
对于任意的 n >= 5,很明显证明 3 * ( n - 3 ) > 2 * ( n - 2 ) > n ,也就是说,绳子的长度大于等于 5 的时候,可以继续剪绳子来得到更优解。所以这道题的最优解的基本单元是 2 和 3,也就是说,最优解中只包含 2 和 3 这两种长度的绳子。因为 3 * 3 * ( n - 6 ) > 2 * 2 * 2 * ( n - 6 ) ,所以说,最优解中 2 的数量不超过 2 个,因为当我有 3 个及 3 个以上的长度为 2 的绳子的时候,可以将其转换成更优解,即 3 * 3
/* 动态规划 */
public class Solution {
public int cutRope(int target) {
if(target < 2){
return 0;
}
if(target == 2){
return 1;
}
if(target == 3){
return 2;
}
int[] products = new int[target + 1];
int val = 0;
int max = 0;
products[2] = 2;
products[3] = 3;
products[4] = 4;
for(int i = 5;i <= target;i++){
for(int j = 2;j <= i/2; j++){
val = products[j] * products[target-j];
if(max < val){
max = val;
}
}
products[i] = max;
}
return products[target];
}
}
/* 贪心算法 */
import java.lang.Math;
public class Solution {
public int cutRope(int target) {
if(target < 2){
return 0;
}
if(target == 2){
return 1;
}
if(target == 3){
return 2;
}
if(target == 4){
return 4;
}
int numOfThree = target / 3;
int numOfTwo = 2 / (target % 3);
return (int)(Math.pow(3,numOfThree) * Math.pow(2,numOfTwo));
}
}