动态规划中的0-1背包问题

本文详细解析了0-1背包问题的动态规划解决方案,通过具体实例讲解了如何利用二维数组模拟物品选择过程,并进一步优化为一维数组减少内存消耗。适合初学者理解和实践。

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

0-1背包问题

输入数据
T表示有T组数据
然后分别输入T组
第一行为物品个数N,背包容量V
第二行为物品价值
第三行为物品占用体积

输出最大价值量
Input
1
5 10
1 2 3 4 5
5 4 3 2 1
Output
14
首先考虑动态规划
将物品个数和背包容量想象为二维数组,行用i表示面临的第i个物品的选择,列用j表示背包容量为j的情况下最优的装载价值。
然后我们开始模拟从第一个物品开始挑选的过程,用两个for循环来模拟这个过程:

for(int i=1;i<=N;i++)
        {
            for(int j=0;j<=V;j++)//注意j从0开始
            {
                if(j>=w[i])
                    s[i][j]=max(s[i-1][j],s[i-1][j-w[i]]+v[i]);
                else
                    s[i][j]=s[i-1][j];
            }
        }

模拟一下过程哈
首先挑选第一个物品,价值1,体积5,在第一个for循环中进行第二个对背包的体积进行的for循环,体积小于5之前的价值s[i][j]肯定都是0不用多讲,从体积大于等于5开始,背包能装入的价值量为1了,第1行后面都一样,接着我们来看第2行。
第二行是第一个for循环循环到i=2的情况,开始挑选第二个物品,还是从体积为1开始循环,直到体积为4可以装第二个物品了,所以s[2][4]=2了,然后关键的地方来了,到体积为5的时候,5>4,所以s[2][5]=s[2-1][5]或者s[2-1][5-物品2的体积]+物品2的价值(也就是s[i-1][j-w[i]]+v[i]),在这里当背包容量大于等于这个挑选的物品时,可以分为两种情况:①不选就等于s[i-1][j]②选则等于s[i-1][j-w[i]]+v[i],这个的意思就是在选第i个物品时,前i-1个物品挑选过的最大价值加上第i个物品的价值(这个时候背包剩余体积需要减去装入第i个物品的体积)

下面我们来改进代码,如果数据非常大,我们创建二维数组就会出现代码内存太大的错误,我们根据这道题完全可以转换为一个一维数组:但是注意,背包容量的那个for循环只能是从后向前,因为我们必须保证前面的数据对后面的数据不会产生影响。

for(int i=1;i<=N;i++)
            for(int j=V;j>0;j--)
        {
            if(j>=w[i])
                s[j]=max(s[j],s[j-w[i]]+v[i]);
            else
                s[j]=s[j];
        }

完整代码:

#include<string.h>
#include<iostream>
using namespace std;
#define MAX_N 1000
#define max(a,b) a>b?a:b
int s[1007];
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        int N,V;
        cin>>N>>V;
        int v[1007],w[1007];
        memset(s,0,sizeof(s));
        for(int i=1;i<=N;i++)
        {
            cin>>v[i];
        }
        for(int i=1;i<=N;i++)
        {
            cin>>w[i];
        }
        for(int i=1;i<=N;i++)
            for(int j=V;j>0;j--)
        {
            if(j>=w[i])
                s[j]=max(s[j],s[j-w[i]]+v[i]);
            else
                s[j]=s[j];
        }
        cout<<s[V]<<endl;

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值