题目:
给你一根长度为n的绳子,请把绳子剪成m段(m和n都是整数,n>1并且m>1), 每段绳子的长度记为k[0],k[1],...,k[m]. 请问k[0]*k[1]*...*k[m]可能的最大乘积是多少?
分析一:
使用动态规划。
代码一(书上的代码):
package offer.xzs.fourteenth;
public class Demo01 {
public static void main(String[] args) {
int muil = getMuil(8);
System.out.println(muil);
}
public static int getMuil(int length) {
if (length < 2) {
return 0;
}
if (length == 2) {
return 1;
}
if (length == 3) {
return 2;
}
int[] results = new int[length + 1];
results[0] = 0;
results[1] = 1;
results[2] = 2;
results[3] = 3;
int max = 0;
//从4开始,是因为4之前的长度剪开得到的乘积数还不如长度本身长,所以到时候直接用长度去运算
for (int i = 4; i <= length; i++) {
max = 0;
for (int j = 1; j <= i / 2; j++) {
int result = results[j] * results[i - j];
if (result > max) {
max = result;
}
results[i] = max;
}
}
max = results[length];
return max;
}
}
更简洁的方法
package offer.xzs.fourteenth;
public class Demo02 {
public static void main(String[] args) {
int muil = getMuil(8);
System.out.println(muil);
}
public static int getMuil(int length) {
int[] dp = new int[length + 1];
dp[1] = 1;
for (int i = 2; i <= length; i++) {
for (int j = 1; j < i; j++) {
dp[i] = Math.max(dp[i], Math.max(j * (i - j), dp[j] * (i - j)));
}
}
return dp[length];
}
}
分析二:
贪婪算法,当绳子长度大于4时,尽可能地多剪长度为 3 的绳子,当剩下的绳子为 4 时,剪成两段长度为2的绳子。
代码二:
package offer.xzs.fourteenth;
public class Demo03 {
public static void main(String[] args) {
int muil = getMuil(8);
System.out.println(muil);
}
public static int getMuil(int length) {
if (length < 2) {
return 0;
}
if (length == 2) {
return 1;
}
if (length == 3) {
return 2;
}
int duan3 = length / 3;
if (length - duan3 * 3 == 1) {
duan3--;
}
int duan2 = (length - duan3 * 3) / 2;
int result = (int) (Math.pow(2, duan2) * Math.pow(3, duan3));
return result;
}
}