我知道如何使用动态编程解决杆切割问题。 但是当我们限制允许的最大切割次数时,动态编程无法给出正确的答案。即使我想不出问题的递归解决方案。救命。
这是问题,
确定通过切割杆和销售件可获得的最大收入
给定一根长度为N的杆,以及长度为i的杆的价格表P(i)。你可以在给定的杆上进行不超过K次切割。
例如:
N = 10
K = 3
| p(1)= 1 | p(2)= 5 | p(3)= 8 | p(4)= 9 | p(5)= 10 | p(6)= 22 | p(7)= 17 | p(8)= 20 | p(9)= 24 | p(10)= 30 |
通过将杆切割成长度为6和4的2个(切割总数= 1,小于K = 3),最大可获得收益为31。
答案 0 :(得分:4)
我们可以通过添加第二维来扩展动态编程解决方案,这是迄今为止的切割数量。
D[n][k]
,使用精确n
剪辑的k
长度的杆的最大收入可以定义如下:
D[n][k] = max(price[i] + D[n-i-1][k-1]) for all i in {1, 2, ..., n}
由于我们希望最多 K
削减,而不是完全,因此最高收入将为:
maxRevenue(N) = max(D[N][k]) for all k in {1, 2, ..., k}
这将是O(N²K)
,因为我们需要遍历所有k
(与经典问题的O(N²)
相比)。
(Java)代码:
int[] price = {1, 5, 8, 9, 10, 22, 17, 20, 24, 30};
int N = price.length;
int K = 3;
int[][] D = new int[N+1][K+1];
for (int n = 1; n <= N; n++)
D[n][0] = price[n-1];
for (int k = 1; k <= K; k++)
for (int n = 0; n <= N; n++)
for (int i = 0; i <= n-1; i++)
D[n][k] = Math.max(D[n][k], price[i] + D[n-i-1][k-1]);
int best = 0;
for (int k = 0; k <= K; k++)
best = Math.max(best, D[N][k]);
System.out.println(best);