51nod 1086 背包问题v2 多重背包

本文介绍了一种解决多重背包问题的有效算法。通过将每种物品按数量拆分为多个虚拟物品,利用01背包问题的解法进行优化,避免了直接应用01背包方法导致的时间复杂度过高的问题。

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

1086 背包问题 V2
基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 收藏 关注
有N种物品,每种物品的数量为C1,C2……Cn。从中任选若干件放在容量为W的背包里,每种物品的体积为W1,W2……Wn(Wi为整数),与之相对应的价值为P1,P2……Pn(Pi为整数)。求背包能够容纳的最大价值。
Input
第1行,2个整数,N和W中间用空格隔开。N为物品的种类,W为背包的容量。(1 <= N <= 100,1 <= W <= 50000)
第2 - N + 1行,每行3个整数,Wi,Pi和Ci分别是物品体积、价值和数量。(1 <= Wi, Pi <= 10000, 1 <= Ci <= 200)
Output
输出可以容纳的最大价值。
Input示例
3 6
2 2 5
3 3 8
1 4 1
Output示例
9
相关问题

多重背包是每种物品有一定的数量
题上为例
我们可以发现
将01背包的代码 按照每种物品的数量输入的时候
得到的结果就是正确答案

但是肯定的是
如果直接用这种思想做的话会超时
所以要多一步的优化

这里写图片描述

我们 将第一件物品变成k个种类的物品

首先

体积 价值 物品剩余数量
2 2 4
4 4 2
4 4 0 最后一步的处理是为了让剩余的物品变成一类物品

3 3 7
6 6 5
12 12 1
3 3 0

以上步奏就是对于多重背包关于01背包的优化

#include <iostream>
#include <stdio.h>
#include <iomanip>
#include <cmath>
#include <cstring>
#include <string>
using namespace std;
long long d[100000],p[100000];
int main()
{
    long long t,v;
    long long n1[1000],w1[100],s1[1000];
    long long n[100000],w[100000];
    while(cin>>t>>v)
    {
        memset(n,0,sizeof(n));
        memset(w,0,sizeof(w));
        memset(d,0,sizeof(d));
        memset(p,0,sizeof(p));
        memset(w1,0,sizeof(w1));
        memset(n1,0,sizeof(n1));
        memset(s1,0,sizeof(s1));
        long long i,x=0,y,j=0,r=1;
        for(i=0;i<t;i++)
        {
            cin>>n1[i]>>w1[i]>>s1[i];
            x=n1[i];
            y=w1[i];
            r=1;
            for(;;)
            {
                if(s1[i]-r<0)
                {
                    n[j]=n1[i]*s1[i]; 
                    w[j]=w1[i]*s1[i];
                    j++;
                    break;
                }
                n[j]=x;
                w[j]=y;
                s1[i]-=r;
                j++;
                r*=2;
                x=x*2;
                y=y*2;
            }
            j++;
        }
        t=j;
        /*for(i=0;i<t;i++) cout<<n[i]<<' '<<w[i]<<endl;*/
        for(i=1;i<=t;i++)
        {
            for(j=0;j<=v;j++) p[j]=d[j];
            for(j=n[i-1];j<=v;j++)
            {
                d[j]=max(p[j-n[i-1]]+w[i-1],p[j]);
            }
        }
        cout<<d[v]<<endl;
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值