ACM算法笔记(八)背包问题_多重背包

问题描述:

现在给你一个容量为V的背包,有N个物品,其中第i件物品的重量为wi,价值为vi,第i件物品一共有si件,问在有限的容量内,最多可以拿到多少价值的物品。

题目分析:

仔细一看,多重背包问题和完全背包问题的差距就在物品的个数上,完全背包问题是同一类物品有无数件,但多重背包不让着你,多重背包给你规定了最多件数。仔细看看还挺有意思,01背包是要么0件要么1件,多重背包是要么可以选0~si件,而完全背包则是可以选0~∞件。

那我们拓展一下思维,这是规定了同类物品最多能拿的个数,要是规定了第i类物品最少要拿多少件呢?很容易想到,只需要初始化的时候提前拿一些,就转换成了01背包问题咯(题外话题外话)

回归正题,多重背包问题就是在完全背包问题加了一个限制条件,“最多能拿si件”。那我们只需要改一改完全背包问题的代码,不就迎刃而解了吗?

假设取前i件物品装入容量为V的背包,第i件物品拿k件所得到的最大值为dp[i][j]

那么dp[i][j]=max(dp[i][j],dp[i-1][j-k*w[i]]+k*v[i])这里的k的范围是:0≤k≤s[i]

于是代码如下...

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int MAXN=1e3+7;
int w[MAXN],N,V,v[MAXN],dp[MAXN][MAXN],s[MAXN];
int main()
{
    memset(dp,0,sizeof(dp));
    cin>>V>>N;
    for(int i=1;i<=N;i++)
    {
        cin>>w[i]>>v[i]>>s[i];
    }
    for(int i=1;i<=N;i++)
    {
        for(int j=0;j<=V;j++)
        {
            for(int k=0;k<=s[i]&&k*w[i]<=j;k++)
            {
              dp[i][j]=max(dp[i][j],dp[i-1][j-k*w[i]]+k*v[i]);
            }
        }
    }
    cout<<dp[N][V]<<endl;
    return 0;
}//二维
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int MAXN=1e3+7;
int w[MAXN],N,V,v[MAXN],dp[MAXN],s[MAXN];
int main()
{
    memset(dp,0,sizeof(dp));
    cin>>V>>N;
    for(int i=1;i<=N;i++)
    {
        cin>>w[i]>>v[i]>>s[i];
    }
    for(int i=1;i<=N;i++)
    {
        for(int j=V;j>=0;j--)
        {
            for(int k=0;k<=s[i]&&k*w[i]<=j;k++)
            {
                dp[j]=max(dp[j],dp[j-k*w[i]]+k*v[i]);
            }
        }
    }
    cout<<dp[V]<<endl;
    return 0;
}//一维

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值