题目描述: 把一根长度为 n 的绳子剪成 m 段,使 m 段绳子的长度乘积最大(m > 1)。
解法一: 动态规划,子问题的最优解存储在数组 dp 中。
public int maxCutting(int length){
if(length < 2) return 0;
if(length == 2)return 1;
if(length == 3)return 2;
int[] dp = new int[length + 1];
dp[0] = 0;
dp[1] = 1;
dp[2] = 2;
dp[3] = 3;
int max = 0;
for(int i = 4; i <= length; i++){
max = 0;
for(int j = 1;j <= i/2; j++){
int t = dp[j]*dp[i - j];
if(t > max) max = t;
}
dp[i] = max;
}
return dp[length];
}
解法二: 贪婪算法。当 n >= 5
时,尽可能多地剪长度为 3
的绳子;当剩下的绳子长度为 4
时,把绳子剪成两端长度为 2
的绳子。
当 n < 5
时,无论怎么剪切,乘积 product <= n
,n
为 4
时,product
最大为 2 * 2 = 4
。
当 n >= 5
时,可以证明 2(n-2)>n
并且 3(n-3)>n
。而且 3(n-3)>=2(n-2)
。所以我们应该尽可能地多剪长度为3
的绳子段。
public int maxCutting(int length){
if(length < 2) return 0;
if(length == 2)return 1;
if(length == 3)return 2;
int timesOf3 = length / 3 ;
if(length - timesOf3 * 3 == 1) {
timesOf3 -= 1 ;
}
int timesOf2 = (length - timesOf3 * 3) / 2 ;
return (int) (Math.pow(3, timesOf3) * Math.pow(2, timesOf2)) ;
}