多重背包模型讲解(附C++代码实现)

1.概念解析

    ‌多重背包问题是一种动态规划问题,其核心在于如何在有限数量的物品中选择,使得背包中的物品总价值最大,同时不超过背包的容量限制。

2.举例了解

宝物筛选

题目描述

终于,破解了千年的难题。小 FF 找到了王室的宝物室,里面堆满了无数价值连城的宝物。

这下小 FF 可发财了,嘎嘎。但是这里的宝物实在是太多了,小 FF 的采集车似乎装不下那么多宝物。看来小 FF 只能含泪舍弃其中的一部分宝物了。

小 FF 对洞穴里的宝物进行了整理,他发现每样宝物都有一件或者多件。他粗略估算了下每样宝物的价值,之后开始了宝物筛选工作:小 FF 有一个最大载重为 W W W 的采集车,洞穴里总共有 n n n 种宝物,每种宝物的价值为 v i v_i vi,重量为 w i w_i wi,每种宝物有 m i m_i mi 件。小 FF 希望在采集车不超载的前提下,选择一些宝物装进采集车,使得它们的价值和最大。

输入格式

第一行为一个整数 n n n W W W,分别表示宝物种数和采集车的最大载重。

接下来 n n n 行每行三个整数 v i , w i , m i v_i,w_i,m_i vi,wi,mi

输出格式

输出仅一个整数,表示在采集车不超载的情况下收集的宝物的最大价值。

输入输出样例

输入 #1

4 20
3 9 3
5 9 1
9 4 2
8 1 3

输出 #1

47

提示

对于 30 % 30\% 30% 的数据, n ≤ ∑ m i ≤ 1 0 4 n\leq \sum m_i\leq 10^4 nmi104 0 ≤ W ≤ 1 0 3 0\le W\leq 10^3 0W103

对于 100 % 100\% 100% 的数据, n ≤ ∑ m i ≤ 1 0 5 n\leq \sum m_i \leq 10^5 nmi105 0 ≤ W ≤ 4 × 1 0 4 0\le W\leq 4\times 10^4 0W4×104 1 ≤ n ≤ 100 1\leq n\le 100 1n100

思路解析

    建议先食用01背包问题模型讲解和【题解】—— [NOIP2005 普及组] 采药完全背包模型讲解和【题解】——疯狂的采药

    有一种比较直接的方法。类似于完全背包,只需要将枚举每件物品的件数那一层循环的限制条件改成k<=nums[i]&&k*a[i].weight<=j //nums[i]表示第i件物品的数量就行了。但是这样的方法太过暴力,还有更好的方法吗?

    其实,我们可以将这道题转换成01背包。用上面的样例来说明。

4 20
3 9 3
5 9 1
9 4 2
8 1 3

    我们可以将每一件物品铺平,放到数组a里面去。并不需要把它们当成一堆物品来处理。此时的a数组如下(只展示某件物品的价值和编号(按输入顺序来定,编号不存储a数组中,展示出仅为了方便理解)):

编号111233444
价值333544111
下标123456789

    最后只需要按01背包来处理就行了。

3.示例代码

#include<bits/stdc++.h>
using namespace std;
#define MAXM 1010//m的数据范围,可根据题目修改
#define MAXN 1010//n的数据范围,可根据题目修改
//m表示背包的重量,n表示物品的数量,dp[j]表示当前重量上限为j时的最大价值
int m, n, dp[MAXM], cnt;
struct object{
    int weight, value;//储存每个物品的重量和价值
    object(int _w = 0, int _v = 0) :weight(_w), value(_v) {};
}a[MAXN];
int main(){
    scanf("%d%d", &m, &n);
    for (int i = 1; i <= n; i++){//输入n个物品
        int w, v, m;//存储当前物品的重量,价值和件数 
        scanf("%d%d", &w, &v, &m);
        for (int j = 1; j <= n; j++)a[++cnt] = object(w, v);//展开 
    }
    for (int i = 1; i <= cnt; i++)
        for (int j = m; j >= a[i].weight; j--)
            //枚举所有能装下a[i]的重量
            dp[j] = max(dp[j], dp[j - a[i].weight] + a[i].value);
    printf("%d\n", dp[m]);
    return 0;
}

    注意:以上代码不能通过此题。需要使用二进制优化。这里由于篇幅关系就先不展开讨论。

喜欢就订阅此专辑吧!

【蓝胖子编程教育简介】
蓝胖子编程教育,是一家面向青少年的编程教育平台。平台为全国青少年提供最专业的编程教育服务,包括提供最新最详细的编程相关资讯、最专业的竞赛指导、最合理的课程规划等。本平台利用趣味性和互动性强的教学方式,旨在激发孩子们对编程的兴趣,培养他们的逻辑思维能力和创造力,让孩子们在轻松愉快的氛围中掌握编程知识,为未来科技人才的培养奠定坚实基础。

欢迎扫码关注蓝胖子编程教育
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蓝胖子教编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值