题目描述
给你一根长度为n的绳子,请把绳子剪成整数长的m段(m、n都是整数,n>1并且m>1,m<=n),每段绳子的长度记为k[1],…,k[m]。请问k[1]x…xk[m]可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
练习地址
实现
public class C14_MaxProductAfterCutting {
/**
* 动态规划:时间O(n²) 空间(n)
* 贪心算法:时间 空间 O(1)
*/
static int cut(int n) {
if (n < 2) return 0;
if (n == 2) return 1;
if (n == 3) return 2;
// products 存储子问题的最优解 0-n
// 表示数组中第i个元素表示把长度为i的绳子剪成若干段后各段程度乘积的最大值
// 即 f(i)
int[] products = new int[n + 1];
/*
这部分初始值不太理解,特殊处理,不再拆分?
为使乘积最大,只有长度为 2 和 3的绳子不应再切分,且 3 比 2 更优
*/
products[0] = 0;
products[1] = 1;
products[2] = 2;
products[3] = 3;
int max = 0; // 复用
for (int i = 4; i <= n; i++) { //i递增,即自下而上计算
max = 0;
for (int j = 1; j <= i / 2; j++) { // 求f(i)前,f(j)(0<i<j)已求出
int product = products[j] * products[i - j]; //f(j)*f(i-j)的所有可能,比较获得最大值
if (max < product) {
max = product;
}
products[i] = max;
}
}
return products[n];
}
//贪婪算法
static int cut2(int n) {
if (n < 2) return 0;
if (n == 2) return 1;
if (n == 3) return 2;
int timesOf3 = n / 3; // 尽可能取长度为3
if (n - timesOf3 * 3 == 1) { // 当长度=4,不能再取3的
timesOf3 -= 1;
}
int timesOf2 = (n - 3 * timesOf3) / 2;
return (int) (Math.pow(3, timesOf3) * (int) Math.pow(2, timesOf2));
}
}
Test
public static void main(String[] args) {
System.out.println(cut(8));
System.out.println(cut2(8));
}
这是一篇关于如何利用Java解决剪绳子问题的博客。文章介绍了当给定一根长度为n的绳子时,如何通过将其剪成整数长度的m段来最大化所有段的乘积。题目描述中提到,目标是找到一种剪法,使得剪成的m段绳子长度乘积最大。文章提供了具体的实现思路,即贪心算法,并提到了练习链接以供读者进一步实践。

1万+

被折叠的 条评论
为什么被折叠?



