您的位置:首页 > 其它

记录路径的01背包问题

2017-02-23 17:44 1361 查看
在01背包问题中,求出最优解并记录背包内物品,动态规划的方法求其问题,最核心的公式为f[i][j]=max{f[i-1][j],f[i-1][j-weight[i]]+value[i]}

在考虑当前第i个物品是否放入的时候就是比较

前面的i-1个物品放在容量为j的背包中时背包中总价值与

前面的i-1个物品放在容量为j-weight[i]的背包中并加上当前第i个的价值value[i]的总价值

比较完后选择当前i个物品放在j容量的包中的最佳方案。

同时在记录其路径的时候,路径为conf[i][j]=01,若当前f[i][j]为放入第i件物品,则为1,最终形成一个i行j列的矩阵

f形成的矩阵中第N行J列即为前N件物品放在J容量的包中最大价值解。

其路径便从第N行开始输出,路径conf形成的矩阵第N行J列即为第N件物品在包容量为J时是否放入,若N行J列为0,则代表第N件物品未放入J容量的包中,则再看第N-1件物品,若N-1件物品放入了包中即当前位置为1,则需要在包容量J上减去此时的weight[i],如此反复直到物品全部检索完或者容量小于0。

#include<iostream>
using namespace std;
#define N 7
#define V 10

int main(){
int weight[N+1] = {0,5,3,4,7,2,8,1};//重量
int value[N+1] = {0,16,10,14,12,11,20,8};//价值
int big[N+1][V+1] = {0};//前N件物品容量为V的包
int conf[N+1][V+1] = {0};//记录路径
for(int i=1;i<=N;i++){//考虑第i件物品的时候
for(int j=1;j<=V;j++){//包容量为j的时候
if(j<weight[i]){//若当前包容量为j不足以放入第i件物品
big[i][j] = big[i-1][j];//考虑前i件物品时第i件物品不放入,包内物品同前i-1件物品时状态
}else{
int x = big[i-1][j];
int y = big[i-1][j-weight[i]]+value[i];
big[i][j] = x<y?y:x;//比较前i-1件物品j容量的包时的最大价值与前i-1件物品和容量为j减去当前物品重量的容量大小的包并加上当前物品价值时的总价值
conf[i][j] =x<y?1:0;//若决定放入当前物品,则记为i
}
}
}
for(int i = N; i >= 1; i--){ //前N个物品与V容量的包时最优解决方案
for(int j = 1; j <= V; j++){
printf("%4d ", big[i][j]);
}
cout << endl;
}

for(int i = N; i >= 1; i--){//路径矩阵
for(int j = 1; j <= V; j++){
printf("%4d ", conf[i][j]);
}
cout << endl;
}
for(int i = N,j=V; i>0&&j>0; i--){ //路径记录
if(conf[i][j]) {//第i件物品是否放入容量剩余j的包中
printf("i=%d ", i);
j-=weight[i];//减去当前已经放入的物品占值后的剩余包容量
cout << endl;
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  算法