使用1维数组(如A)进行空间优化的0/1背包动态规划算法,其大小等于背包容量,并在每次迭代i时仅覆盖A [w](如果需要),其中A [w]表示考虑前i个项目并且背包容量为w时的总价值。
如果使用此优化,是否有一种方式可以重构选定的物品列表,例如在Bellman Ford算法中可以实现类似的空间优化,并且只要我们保留前任指针的列表,即最后一跳(或第一跳,具体取决于是编写源/目标导向算法)就可以重构最短路径。
以下是我的C++函数,用于使用动态规划解决0/1背包问题,我构建了一个2维向量ans,其中ans [i] [j]表示考虑前i个项目和背包容量j的总价值。我通过反向遍历这个向量ans来重构选定的项目:
如果使用此优化,是否有一种方式可以重构选定的物品列表,例如在Bellman Ford算法中可以实现类似的空间优化,并且只要我们保留前任指针的列表,即最后一跳(或第一跳,具体取决于是编写源/目标导向算法)就可以重构最短路径。
以下是我的C++函数,用于使用动态规划解决0/1背包问题,我构建了一个2维向量ans,其中ans [i] [j]表示考虑前i个项目和背包容量j的总价值。我通过反向遍历这个向量ans来重构选定的项目:
void knapsack(vector<int> v,vector<int>w,int cap){
//v[i]=value of item i-1
//w[i]=weight of item i-1, cap=knapsack capacity
//ans[i][j]=total value if considering 1st i items and capacity j
vector <vector<int> > ans(v.size()+1,vector<int>(cap+1));
//value with 0 items is 0
ans[0]=vector<int>(cap+1,0);
//value with 0 capacity is 0
for (uint i=1;i<v.size()+1;i++){
ans[i][0]=0;
}
//dp
for (uint i=1;i<v.size()+1;i++) {
for (int x=1;x<cap+1;x++) {
if (ans[i-1][x]>=ans[i-1][x-w[i-1]]+v[i-1]||x<w[i-1])
ans[i][x]=ans[i-1][x];
else {
ans[i][x]=ans[i-1][x-w[i-1]]+v[i-1];
}
}
}
cout<<"Total value: "<<ans[v.size()][cap]<<endl;
//reconstruction
cout<<"Items to carry: \n";
for (uint i=v.size();i>0;i--) {
for (int x=cap;x>0;x--) {
if (ans[i][x]==ans[i-1][x]) //item i not in knapsack
break;
else if (ans[i][x]==ans[i-1][x-w[i-1]]+v[i-1]) { //item i in knapsack
cap-=w[i-1];
cout<<i<<"("<<v[i-1]<<"), ";
break;
}
}
}
cout<<endl;
}
A
,但实现使用了一个二维状态空间ans
?所以,基本上 space_optimized 实现也使用了ans
,但是会丢弃较小的i
值的行? - Codor||
条件的另一半之前测试x<w[i-1]
,以便短路运算将防止ans[i-1][x-w[i-1]]
尝试访问负索引处的数组元素,从而可能导致崩溃。 - j_random_hacker