蓝桥杯 Java B 组之背包问题(01背包、完全背包)

Day 1:背包问题(01背包、完全背包)


📖 一、背包问题简介

背包问题是动态规划(DP)中一个经典的优化问题,涉及物品选择容量约束。通常分为以下几类:

  • 01 背包(0/1 Knapsack):每个物品只能选择 一次
  • 完全背包(Unbounded Knapsack):每个物品可以被选择无限次
  • 多重背包:每个物品有固定的数量,不能超过限制。
  • 分组背包:物品被分成多个组,每组只能选一个。

本次重点讨论01 背包完全背包,并通过 "分割等和子集""零钱兑换 II" 来加深理解。


📖 二、01 背包问题

问题描述: 给定 N 个物品和一个容量为 W 的背包,每个物品有一个 重量 w[i]价值 v[i]。求在不超过 W 的情况下,最大价值是多少?

🔹 01 背包的状态转移方程

定义 dp[i][j] 表示i 个物品在容量 j 下的最大价值

  1. 不选第 i 个物品dp[i][j] = dp[i-1][j]
  2. 选第 i 个物品(前提:j >= w[i]):dp[i][j] = dp[i-1][j - w[i]] + v[i]
  3. 最终答案dp[N][W]

🔹 代码实现(01 背包)

public class Knapsack01 {public int knapsack(int W, int[] weights, int[] values, int n) {int[][] dp = new int[n + 1][W + 1];for (int i = 1; i <= n; i++) {for (int j = 1; j <= W; j++) {dp[i][j] = dp[i - 1][j]; // 不选第 i 个物品if (j >= weights[i - 1]) {dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - weights[i - 1]] + values[i - 1]);}}}return dp[n][W];}public static void main(String[] args) {Knapsack01 knapsack = new Knapsack01();int[] weights = {2, 3, 4, 5};int[] values = {3, 4, 5, 6};int W = 5;int n = weights.length;System.out.println("最大价值: " + knapsack.knapsack(W, weights, values, n)); // 输出 7}
}

🔹 时间复杂度

O(n * W),其中 n 是物品数量,W 是背包容量。


📖 三、完全背包问题

问题描述: 与 01 背包 不同,完全背包允许每个物品选取无限次

🔹 完全背包的状态转移方程

  1. 不选第 i 个物品dp[i][j] = dp[i-1][j]
  2. k 次第 i 个物品(前提:j >= k * w[i]): dp[i][j]=max⁡(dp[i][j],dp[i][j−k×w[i]]+k×v[i])dp[i][j] = \max(dp[i][j], dp[i][j - k \times w[i]] + k \times v[i])

优化版

dp[i][j]=max⁡(dp[i−1][j],dp[i][j−w[i]]+v[i])dp[i][j] = \max(dp[i-1][j], dp[i][j-w[i]] + v[i])

注意:完全背包的状态转移是从 dp[i][j-w[i]] 来的,而不是 dp[i-1][j-w[i]],表示可以重复选取当前物品

🔹 代码实现(完全背包)

public class KnapsackComplete {public int knapsack(int W, int[] weights, int[] values, int n) {int[] dp = new int[W + 1];for (int i = 0; i < n; i++) {for (int j = weights[i]; j <= W; j++) { // 正序遍历dp[j] = Math.max(dp[j], dp[j - weights[i]] + values[i]);}}return dp[W];}public static void main(String[] args) {KnapsackComplete knapsack = new KnapsackComplete();int[] weights = {2, 3, 4, 5};int[] values = {3, 4, 5, 6};int W = 5;int n = weights.length;System.out.println("最大价值: " + knapsack.knapsack(W, weights, values, n)); // 输出 8}
}

🔹 时间复杂度

O(n * W),但使用了一维 dp 数组,空间复杂度从 O(n*W) 降到了 O(W)


📖 四、练习 1:分割等和子集(Subset Sum)

题目描述: 给定一个非负整数数组 nums,判断是否可以将其分割为两个子集,使得两个子集的和相等。

🔹 思路

  • 转化为 01 背包问题
    • 目标是找到一个子集,使得其和为 sum/2
    • 如果 sum 为奇数,则直接返回 false
    • 状态定义dp[j] 表示能否填满容量 j 的背包
    • 状态转移方程dp[j] = dp[j] || dp[j - nums[i]]

🔹 代码实现

import java.util.*;public class PartitionEqualSubsetSum {public boolean canPartition(int[] nums) {int sum = Arrays.stream(nums).sum();if (sum % 2 != 0) return false; // 奇数直接返回 falseint target = sum / 2;boolean[] dp = new boolean[target + 1];dp[0] = true;for (int num : nums) {for (int j = target; j >= num; j--) { // 01 背包,倒序遍历dp[j] = dp[j] || dp[j - num];}}return dp[target];}public static void main(String[] args) {PartitionEqualSubsetSum solution = new PartitionEqualSubsetSum();int[] nums = {1, 5, 11, 5};System.out.println(solution.canPartition(nums)); // 输出 true}
}

时间复杂度:O(n * sum/2)sum 是数组和。


📖 五、练习 2:零钱兑换 II(Coin Change II)

题目描述: 给定不同面额的硬币 coins 和一个总金额 amount,求总共有多少种方式可以凑成 amount

🔹 代码实现

public class CoinChange2 {public int change(int amount, int[] coins) {int[] dp = new int[amount + 1];dp[0] = 1; // 组合数初始化for (int coin : coins) {for (int j = coin; j <= amount; j++) { // 完全背包,正序遍历dp[j] += dp[j - coin];}}return dp[amount];}public static void main(String[] args) {CoinChange2 solution = new CoinChange2();int[] coins = {1, 2, 5};int amount = 5;System.out.println(solution.change(amount, coins)); // 输出 4}
}

时间复杂度:O(n * amount)


📖 六、总结

01 背包 vs 完全背包

背包类型状态转移
01 背包dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]] + v[i])
完全背包dp[i][j] = max(dp[i-1][j], dp[i][j-w[i]] + v[i])

🎯 练习建议

  • 先熟练掌握 01 背包,再理解 完全背包 的正序遍历优化。
  • 多练习 变种题型,如 分割等和子集、零钱兑换 II

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/22881.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

单页图床HTML源码+本地API接口图床系统修复版源码

源码介绍 图床系统是一种用于存储和管理图片文件的在线服务。它允许用户上传图片文件&#xff0c;并生成相应的图片链接&#xff0c;从而方便用户在网页、社交媒体或其他平台上分享图片。 PS:源码压缩包分为两个版本&#xff0c;一个是调用360第三方api接口&#xff0c;另外一…

初级渗透测试工程师需要学什么?网络安全零基础入门到精通教程建议收藏!

1、前言 本文主要介绍如何成为一名初级的渗透测试工程师所需要学习的内容&#xff0c;后续也会基于此将自己的学习总结、心得记录下来。相信在不断坚持下&#xff0c;争取在今年五月初成为一名初级的渗透测试工程师。 2、涉及知识领域 基础网络知识&#xff1a; 理解TCP/IP协…

DeepSeek写俄罗斯方块手机小游戏

DeepSeek写俄罗斯方块手机小游戏 提问 根据提的要求&#xff0c;让DeepSeek整理的需求&#xff0c;进行提问&#xff0c;内容如下&#xff1a; 请生成一个包含以下功能的可运行移动端俄罗斯方块H5文件&#xff1a; 核心功能要求 原生JavaScript实现&#xff0c;适配手机屏幕 …

网络安全营运周报

&#x1f345; 点击文末小卡片 &#xff0c;免费获取网络安全全套资料&#xff0c;资料在手&#xff0c;涨薪更快 第三章网络安全基础 一、网络安全概述 1、网络安全现状及安全挑战 网络安全范畴极其广泛&#xff0c;可以说是涉及多方面。 因为计算机病毒层出不穷以及黑客的…

C#中级教程(1)——解锁 C# 编程的调试与错误处理秘籍

一、认识错误&#xff1a;编程路上的 “绊脚石” 在 C# 编程中&#xff0c;错误大致可分为两类&#xff1a;语法错误和语义错误&#xff08;逻辑错误&#xff09;。语法错误就像是写作文时的错别字和病句&#xff0c;编译器一眼就能识别出来&#xff0c;比如变量名拼写错误、符…

QML Button 部件的使用

按钮也是程序开发中最经常用到的部件&#xff0c;当然其也是比较简单&#xff0c;只需要懂得最基本的操作即可&#xff1b; Button {id: btnwidth: 100height: 50 } 生成一个最基本的按钮 text 属性可以设置按钮文本&#xff1b; flat 属性设置为true时&#xff0c;只有鼠标…

Starlink卫星动力学系统仿真建模第七讲-卫星姿轨控系统(Attitude and Orbit Control System, AOCS)设计规范

以下是一份卫星姿轨控系统&#xff08;Attitude and Orbit Control System, AOCS&#xff09;设计规范的框架和核心内容示例&#xff0c;供参考&#xff1a; 卫星姿轨控系统&#xff08;AOCS&#xff09;设计规范 1. 总则 1.1 目的 本规范旨在规定卫星姿轨控系统的设计要求、…

DINOv2 + yolov8 + opencv 检测卡车的可拉拽雨覆是否完全覆盖

最近是接了一个需求咨询图像处理类的&#xff0c;甲方要在卡车过磅的地方装一个摄像头用检测卡车的车斗雨覆是否完全&#xff0c; 让我大致理了下需求并对技术核心做下预研究 开发一套图像处理软件&#xff0c;能够实时监控经过的卡车并判断其车斗的雨覆状态。 系统需具备以下…

基础dp——动态规划

目录 一、什么是动态规划&#xff1f; 二、动态规划的使用步骤 1.状态表示 2.状态转移方程 3.初始化 4.填表顺序 5.返回值 三、试题讲解 1.最小花费爬楼梯 2.下降路径最小和 3.解码方法 一、什么是动态规划&#xff1f; 动态规划&#xff08;Dynamic Programming&…

Java+Vue+SpringBoot+数据可视化的小吃摊位管理平台(程序+论文+讲解+安装+调试+售后)

感兴趣的可以先收藏起来&#xff0c;还有大家在毕设选题&#xff0c;项目以及论文编写等相关问题都可以给我留言咨询&#xff0c;我会一一回复&#xff0c;希望帮助更多的人。 系统介绍 在繁华的美食街区&#xff0c;美食摊位星罗棋布&#xff0c;每天都上演着热闹非凡的烟火…

链表-基础训练(二)链表 day14

两两交换链表中的节点 题目示意&#xff1a; 给定一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后的链表。 你不能只是单纯的改变节点内部的值&#xff0c;而是需要实际的进行节点交换。 原先我的思路是图像上的思路&#xff0c;但是我感觉还是很复杂…

进程概念、PCB及进程查看

文章目录 一.进程的概念进程控制块&#xff08;PCB&#xff09; 二.进程查看通过指令查看进程通过proc目录查看进程的cwd和exe获取进程pid和ppid通过fork()创建子进程 一.进程的概念 进程是一个运行起来的程序&#xff0c;而程序是存放在磁盘的&#xff0c;cpu要想执行程序的指…

极客大学 java 进阶训练营怎么样,图文详解

Spring 思维导图 Spring 源码学习笔记 有关微服务的面试题&#xff1a; Dubbo中zookeeper做注册中心&#xff0c;如果注册中心集群都挂掉&#xff0c;发布者和订阅者之间还能通信么&#xff1f;微服务学习笔记 有关分布式的面试题&#xff1a; 消息幂等:如何保证消息不被重复…

如何手动设置u-boot的以太网的IP地址、子网掩码、网关信息、TFTP的服务器地址,并进行测试

设置IP地址 运行下面这条命令设置u-boot的以太网的IP地址&#xff1a; setenv ipaddr 192.168.5.9设置子网掩码 运行下面这条命令设置u-boot的以太网的子网掩码&#xff1a; setenv netmask 255.255.255.0设置网关信息 运行下面这条命令设置u-boot的网关信息&#xff1a; …

使用大语言模型对接OA系统,实现会议室预定功能

随着人工智能技术的不断进步&#xff0c;越来越多的企业开始借助 AI 助手来提高工作效率&#xff0c;尤其是在日常事务的自动化处理中。比如&#xff0c;在许多公司里&#xff0c;会议室的预定是一个常见且频繁的需求&#xff0c;通常需要员工手动检查空闲时间并做出选择。而通…

单链表:数据结构中的灵活“链条”

目录 &#x1f680;前言&#x1f914;单链表是什么&#xff1f;&#x1f4af;单链表的结构特点&#x1f4af;单链表的用途 ✍️单链表的实现与接口解释&#x1f4af;打印链表&#x1f4af;尾插操作&#x1f4af;头插操作&#x1f4af;头删操作&#x1f4af;尾删操作&#x1f4a…

Redis面试宝典【刷题系列】

文章目录 一、什么是Redis&#xff1f;二、Redis相比Memcached有哪些优势&#xff1f;三、Redis支持的数据类型有哪些&#xff1f;四、Redis的主要消耗的物理资源是什么&#xff1f;五、Redis的全称是什么&#xff1f;六、Redis有哪些数据淘汰策略&#xff1f;七、为什么Redis需…

uni-app集成sqlite

Sqlite SQLite 是一种轻量级的关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;广泛应用于各种应用程序中&#xff0c;特别是那些需要嵌入式数据库解决方案的场景。它不需要单独的服务器进程或系统配置&#xff0c;所有数据都存储在一个单一的普通磁盘文件中&am…

pytest-html

首先安装pytest-html库 #执行命令 pytest --htmlreport.html ./pytest-html.pyimport pytest import logging def test_pass():"""用例通过"""assert Truedef test_fail():"""用例失败"""assert Falsedef test_e…

kafka为什么这么快?

前言 Kafka的高效有几个关键点&#xff0c;首先是顺序读写。磁盘的顺序访问速度其实很快&#xff0c;甚至比内存的随机访问还要快。Kafka在设计上利用了这一点&#xff0c;将消息顺序写入日志文件&#xff0c;这样减少了磁盘寻道的时间&#xff0c;提高了吞吐量。与传统数据库的…