记录路径的01背包问题

在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;
} 
  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值