我正在尝试找出如何为可以通过动态编程解决的问题找到最佳路径。我对我们尝试优化空间的情况很感兴趣。
为了更好地解释我的问题,让我们考虑背包问题。
有3个项目,如下所示:
I1 I2 I3
---------------------------
Val 5 4 3
Weight 4 5 2
最佳路径是为最佳解决方案应选择的项目。
重复关系如下:
Let n be the nth item
let c be the remaining capacity in the knapsack
f(n, c) = 0 // if n=0
f(n, c) = f(n-1, c) // if weight[n] > c
f(n, c) = max(f(n-1, c), value[n] + f(n-1, c-weight[n])) // if weight[n] <= c
我已经基于这种递归关系(在Java中)编写了一个DP解决方案,而没有进行如下空间优化:
public static void main(String[] args) {
int[] value = {5, 4, 3};
int[] weight = {4, 5, 2};
int capacity = 9;
int[][] dp = new int[value.length+1][capacity+1];
for(int i=0; i<=value.length; i++) {
for(int j=0; j<=capacity; j++) {
if(i==0) {
dp[i][j] = 0;
} else {
if(weight[i-1] <= j){
dp[i][j] = Math.max(dp[i-1][j], value[i-1] + dp[i-1][j - weight[i-1] ]);
} else {
dp[i][j] = dp[i-1][j];
}
}
}
}
System.out.println("optimal value is: " + dp[value.length][capacity]);
}
这将打印出最优解为9。
我现在要查找构成最佳解决方案的项目(在本例中为I1,I2)。
我使用的逻辑如下:
矩阵dp [] []如下:
0 0 0 0 0 0 0 0 0 0
0 0 0 0 5 5 5 5 5 5
0 0 0 0 5 5 5 5 5 9
0 0 3 3 5 5 8 8 8 9
第4行(索引3)对应于项目3,因此我将dp [3] [9](右下角)与dp [2] [9]进行了比较。由于两个值相同,因此我知道未选择项目3 。我去dp [2] [9]。
此操作的结果是:[1,1,0]其中1表示item1,采用item2,0表示未采用item3。
我的问题是:
优化空间时,如何找到路径(在这种情况下为挑选的物品)?甚至有可能吗?
例如,我可以使用2个数组而不是使用矩阵来更改程序,如下所示:
public static void main(String[] args) {
int[] value = {5, 4, 3};
int[] weight = {4, 5, 2};
int capacity = 9;
int[] row0 = new int[capacity+1];
int[] row1 = new int[capacity+1];
for(int i=0; i<=3; i++) {
for(int j=0; j<=capacity; j++) {
if(i==0) {
row1[j] = 0;
} else {
if(weight[i-1] <= j) {
row1[j] = Math.max(row0[j], value[i-1]+ row0[j-weight[i-1]]);
} else {
row1[j] = row0[j];
}
}
}
for(int j = 0; j< row0.length; j++)
row0[j] = row1[j];
}
System.out.println("optimal value is: " + row1[capacity]);
}
如果这样做,最多只能有最后两行:
row0 = { 0 0 0 0 5 5 5 5 5 9 }
row1 = { 0 0 3 3 5 5 8 8 8 9 }
如何仅使用此信息来追溯路径?
答案 0 :(得分:1)
没有所有DP问题的好解决方案。
例如,对于这个问题,我将使用每个可访问的和保留一个位掩码,以指示选择要生成该和的元素。这适用于背包,因为元素的数量很少,选择顺序无关紧要。
对于许多其他DP问题(例如,LCS或最短路径),可以很好地将路径记住为反向链接列表。列表有尾巴,通常您必须记住的那些都有相似的历史。您可能经常需要扫描结构以确保其仍然紧凑。确实需要时,可以删除第N个元素,然后在重建路径时需要进行一次小的搜索以连接每对元素。