多重背包(小明的背包3)

简介: 多重背包(小明的背包3)

题目

小明有一个容量为 V 的背包。

这天他去商场购物,商场一共有 N 种物品,第 i 种物品的体积为 wi ,价值为 vi ,数量为 si。

小明想知道在购买的物品总体积不超过 V的情况下所能获得的最大价值为多少,请你帮他算算。

**输入描述:

输入第 1 行包含两个正整数 N,V,表示商场物品的数量和小明的背包容量。

第2∼N+1 行包含 3 个正整数 w,v,s,表示物品的体积和价值。

1<N≤10^2, 1<V<2 ×10^2, 1 ≤wi, vi,Si ≤ 2× 10^2。

**输出描述:

输出一行整数表示小明所能获得的最大价值。

**输入输出样例

示例:

**输入

3 30

1 2 3

4 5 6

7 8 9

**输出

39

运行限制

最大运行时间:1s

最大运行内存: 256M

题解

解题思路:

由于每个物品的总数量 * 总体积不确定,所以我们必须对对每个物品进行单独分析:

对于当前分析的该种物品,如果其(数量*体积)>(背包的总容量), 则当做完全背包来处理,

否则,

将该物品的进行二进制拆分,(二进制优化的大概思想是:一个数可以拆分为多个"2的某次方" + “一个常数c”,通过组合这些拆分出来的数,同样可以在dp的过程中组合出所有的可能数,这就避免了从1~n这样去枚举每一种情况,从而降低时间复杂度),将拆分出的不同数量的同种物品看作为一种新物品,然后将这种新物品按01背包的方式进行处理(这里用的是降维的01背包,即滚动数组)。

代码如下(Java):

import java.io.*;
public class Main {
    static int N = 1005;
    static int M = 2005;
    static int n, m;
    static int[] dp = new int[M];
    static int[] w = new int[N];
    static int[] v = new int[N];
    static int[] num = new int[N];
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    public static void main(String[] args) throws IOException {
        String[] firstLine = br.readLine().split(" ");
        m = Integer.parseInt(firstLine[0]);
        n = Integer.parseInt(firstLine[1]);
        for (int i = 1; i <= m; i++) {
            String[] nextLine = br.readLine().split(" ");
            w[i] = Integer.parseInt(nextLine[0]);
            v[i] = Integer.parseInt(nextLine[1]);
            num[i] = Integer.parseInt(nextLine[2]);
        }
        for (int i = 1; i <= m; i++)
            MultiplePack(w[i], v[i], num[i]);
        System.out.println(dp[n]);
    }
    static void MultiplePack(int weight, int value, int number) {
        if (number * weight > n) CompletePack(weight, value);
        else {
            int k = 1;
            while (k <= number) {
                ZeroOnePack(k * weight, k * value);
                number -= k;
                k = k << 2;
            }
            if (number != 0) ZeroOnePack(number * weight, number * value);
        }
    }
    static void ZeroOnePack(int weight, int value) {
        for (int i = n; i >= weight; i--)
            dp[i] = Math.max(dp[i], dp[i - weight] + value);
    }
    static void CompletePack(int weight, int value) {
        for (int i = weight; i <= n; i++)
            dp[i] = Math.max(dp[i], dp[i - weight] + value);
    }
}

总结

背包问题是动态规划的一种常见考法,我们不仅要学会01和完全背包,还要灵活运用,来解决多重背包的问题。

文章粗浅,希望对大家有帮助!

相关文章
|
6月前
|
数据采集 机器学习/深度学习 人工智能
运维人的“福音”?AI 驱动的自动化网络监控到底香不香!
运维人的“福音”?AI 驱动的自动化网络监控到底香不香!
639 0
|
前端开发 数据库 数据安全/隐私保护
【项目实战】登录与注册业务的实现(前端+后端+数据库)
【项目实战】登录与注册业务的实现(前端+后端+数据库)
3010 0
【项目实战】登录与注册业务的实现(前端+后端+数据库)
|
7月前
|
SQL 存储 关系型数据库
SQL优化策略与实践:组合索引与最左前缀原则详解
本文介绍了SQL优化的多种方式,包括优化查询语句(避免使用SELECT *、减少数据处理量)、使用索引(创建合适索引类型)、查询缓存、优化表结构、使用存储过程和触发器、批量处理以及分析和监控数据库性能。同时,文章详细讲解了组合索引的概念及其最左前缀原则,即MySQL从索引的最左列开始匹配条件,若跳过最左列,则索引失效。通过示例代码,展示了如何在实际场景中应用这些优化策略,以提高数据库查询效率和系统响应速度。
290 10
|
人工智能 算法 BI
第十四届蓝桥杯省赛大学C组(C/C++)三国游戏
第十四届蓝桥杯省赛大学C组(C/C++)三国游戏
|
机器学习/深度学习
【机器学习】噪声数据对贝叶斯模型有什么样的影响?
【5月更文挑战第10天】【机器学习】噪声数据对贝叶斯模型有什么样的影响?
|
12月前
|
存储 算法 C语言
用C语言开发游戏的实践过程,包括选择游戏类型、设计游戏框架、实现图形界面、游戏逻辑、调整游戏难度、添加音效音乐、性能优化、测试调试等内容
本文探讨了用C语言开发游戏的实践过程,包括选择游戏类型、设计游戏框架、实现图形界面、游戏逻辑、调整游戏难度、添加音效音乐、性能优化、测试调试等内容,旨在为开发者提供全面的指导和灵感。
510 2
|
人工智能 算法 数据挖掘
编程之美:从代码到艺术
【10月更文挑战第42天】在数字世界的画布上,代码不仅仅是冷冰冰的指令序列,它如同艺术家手中的笔触,能够创作出令人惊叹的作品。本文旨在探索编程的艺术性,揭示如何通过技术实现创意和解决问题的美学。我们将一起走进代码的世界,感受它的结构之美、逻辑之精和创新之力。
180 4
|
编解码 NoSQL Redis
(十一)Netty实战篇:基于Netty框架打造一款高性能的IM即时通讯程序
关于Netty网络框架的内容,前面已经讲了两个章节,但总归来说难以真正掌握,毕竟只是对其中一个个组件进行讲解,很难让诸位将其串起来形成一条线,所以本章中则会结合实战案例,对Netty进行更深层次的学习与掌握,实战案例也并不难,一个非常朴素的IM聊天程序。
441 3
|
搜索推荐 算法 C++
蓝桥杯分糖果、最小化战斗力差距、小蓝零花钱
这是一个关于算法问题的集合,包括三个不同的任务: 1. **分糖果**:肖恩有不同种类的糖果要分给学生,目标是使得到糖果字符串的字典序最大且尽量小。给定糖果种类数和一个初始字符串,输出能达到的最小字典序的最大值。 2. **最小化战斗力差距**:小蓝需要将队员分为两组,每组战斗力差距最小。给定队员数量和战斗力值,找出最小的战斗力差距。 3. **小蓝的零花钱**:小蓝要在序列中分割偶数和奇数,每次分割代价是两端元素差的绝对值。目标是在预算内确定最多能进行多少次这样的分割。 每个问题都提供了输入输出示例和相应的C++代码片段来解决这些问题。