切棒子问题与无限背包问题如出一辙,只是表达形式略有不同:给定一个长度为N的棒子,以及一个同样长度的数组,数组中的第i个元素代表从棒子上切下长度为i的一条所对应的价格,问整个棒子切完后所得价格总和的最大值。
实例如下
N = 8
price = {1, 5, 8, 9, 10, 17, 17, 20}
答案是22, 切下长度2(价格为5)和长度6(价格为17)
使用与无限背包问题相同的解题思路,给定一个长度k,我们可以使用如下的数学表达式
F(k)
= 0, k=0
= max of
price[0] + F(k - 1),
price[1] + F(k - 2),
...
price[k- 1] + F(0),
这里F(k)返回的是棒子长度为k时的最大价格和。切下1个单元,得到价格为price[0],棒子长度减少1;切下2个单元,得到价格为price[2],棒子长度减少2,由此类推。所有可能的切法中的最大值就是F(k)的返回值。
我们使用一个一维数组作为DP存储,其下标就是从0到N的各个数字,依照上面的表达式从小到大依次计算DP数组的每个元素,最后DP[N]中的数值就是问题的最终答案。
Java代码如下
class Solution {
public int cutRod(int price[],int n) {
int[] dp = new int[n + 1];
for (int i = 1; i <= n; i++) {
int maxPrices = 0;
for (int j = 0; j < i; j ++) {
int p = price[j] + dp[i - j -1];
maxPrices = Math.max(maxPrices, p);
}
dp[i] = maxPrices;
}
return dp[n];
}
}