f(n) 为把长度为 n 的一段绳子剪成若干段后(不能不剪),各段长度乘积的最大值,求 f(n)
在剪第一刀的时候,可以将绳子分为 i
和 n-i
的两段,遍历所有情况,找出 max(f(i)*f(n-i))
,这个值就是f(n)
而最优解f(n)
又依赖于子问题 f(i)
和 f(n-i)
的最优解,子问题之间又包括大量的重复部分,所以要从下到上解决这个问题,保存子问题的解,为上层问题提供解的基础。
当绳子的长度为2时,只能剪成长度为1, 1的两段,所以f(2) = 1
当绳子的长度为3时,能剪成1, 1, 1
和 1, 2
选后者, 则f(3) = 2
当绳子的长度大于3时,因为2>f(2), 3>f(3)
,故可以剪成最小长度为2, 3
绳子,不继续剪
由于是自底向上的求解,并且在每个长度下都求出最优解,故需要两层循环,时间复杂度O(n^2)
public static int interBreak(int length) {
if (length < 2) return 0;
if (length == 2) return 1;
if (length == 3) return 2;
int[] products = new int[length + 1];
products[0] = 0;
products[1] = 1;
products[2] = 2;
products[3] = 3;
for (int i = 4; i <= length; i++) {
products[i] = 0; //多余的
for (int j = 1; j <= i / 2; j++) {
int k = products[j] * products[i - j];
products[i] = products[i] < k ? k : products[i];
}
}
return products[length];
}