动态规划之0-1背包问题(C++源码)

本文详细解析了0-1背包问题的动态规划解决方案,通过递归数组p(i,j)来寻找在给定背包容量下,如何选择物品以达到最大价值。文章提供了完整的C++代码实现,并解释了如何通过比较p(i,j)和p(i+1,j)来确定每个物品是否被选中。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

动态规划之0-1背包问题

问题:

物品集合s={1,2,3,4,…,n},物品i的重量为wi,其价值为vi,背包的容量(最大载重量)为W,如何装使物品价值最大。(物品不能分割)

分析:

p(i,j)是背包容量为j,可选物品为i(i+1,…,n)时的最优解
(“将前i个物品放入容量为j的背包中”转化为只考虑物品i)

  1. p(i,j)=p(i+1,j)表示没装入第i个物品或者第i个物品的重量wi超过背包容量j。
  2. p(i,j)=p(i+1,j-wi)+vi表示装入物品i,价值增加vi,背包容量变为j-wi。
  3. 最后一个物品p(n,j),j大于wn,则能装入,价值增加vn,否则不能装入,价值增加0。

代码:

最优值:

#include<bits/stdc++.h>
using namespace std;
#define num 100//物品数量
#define num1 1000//背包容量
int w[num];//物品重量
int v[num];//物品价值
int p[num][num1];//递归数组

void value(int c,int n){//c表示背包容量W,n是物品数量
    //边界
    int jMax=min(w[n]-1,c);
    //先将小的不可以装的置为0,将大于w[n]可以装的置为v[n]   
    for(int j=0;j<=jMAx;j++){
        p[n][j]=0;
    }
    for(int j=w[n];j<=c;j++){
        p[n][j]=v[n];
    }
    //计算递推式
    for(int i=n-1;i>1;i--){
        jMax=min(w[i]-1,c);
        for(int j=0;j<=jMax;j++){
            p[i][j]=p[i+1][j];
        }
        for(int j=w[i];j<=c;j++){
            p[i][j]=max(p[i+1][j],p[i+1][j-w[i]+v[i]);
        }
    }
    p[1][c]=p[2][c];
    if(c>=w[1]){
        p[1][c]=max(p[1][c],p[2][c-w[1]+v[1]);
    }
}

最优解:

//用xi=0或1表示物品i装入或不装入背包
void jie(int c,int n,int x[]){
    for(int i=1;i<n;i++){
        if(p[i][c]==p[i+1][c]){
            x[i]=0;
        }
        else{
            x[i]=1;
            c=c-w[i];
        }
        x[n]=(p[n][c])?1:0;
    }
}

主函数:

int main(){
    int x[num];
    int W;
    cin>>W;
    int n;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>w[i]>>v[i];
    }
    memset(p,0,sizeof(p));
    value(W,n);
    cout<<p[1][W]<<endl;
    jie(W,n,x);
    for(int i=1;i<=n;i++){
        if(x[i]){
            cout<<i<<endl;
        }
    }
    return 0;
}

测试:

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值