news 2026/8/25 3:26:19

[特殊字符] 背包问题详解(0/1 背包、完全背包、多重背包)——附 C++ 实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
[特殊字符] 背包问题详解(0/1 背包、完全背包、多重背包)——附 C++ 实现

🧳 背包问题详解(0/1 背包、完全背包、多重背包)——附 C++ 实现

一、什么是背包问题?

背包问题(Knapsack Problem)是经典的动态规划问题之一:

给定一个容量有限的背包和若干物品,每个物品有体积(或重量)*和*价值,问如何选择物品使得总价值最大**。

根据每个物品可选次数不同,背包问题主要分为:

  • 0/1 背包(每个物品最多选一次)
  • 完全背包(每个物品可以选无限次)
  • 多重背包(每个物品有固定数量)

二、0/1 背包问题

1️⃣ 问题描述

  • 背包容量:W
  • 物品数量:n
  • i个物品:
    • 重量:w[i]
    • 价值:v[i]
  • 每个物品最多选一次

目标:
👉 在不超过背包容量的前提下,使总价值最大。


2️⃣ 状态定义

令:

dp[j] = 容量为 j 时能获得的最大价值

3️⃣ 状态转移方程

对于第i个物品:

dp[j] = max(dp[j], dp[j - w[i]] + v[i])

⚠️关键点
j必须从大到小遍历,防止一个物品被选多次。


4️⃣ C++ 实现(0/1 背包)

#include<bits/stdc++.h>usingnamespacestd;intmain(){intn,W;cin>>n>>W;vector<int>w(n),v(n);for(inti=0;i<n;i++){cin>>w[i]>>v[i];}vector<int>dp(W+1,0);for(inti=0;i<n;i++){for(intj=W;j>=w[i];j--){dp[j]=max(dp[j],dp[j-w[i]]+v[i]);}}cout<<dp[W]<<endl;return0;}

三、完全背包问题

1️⃣ 问题描述

与 0/1 背包类似,但:

每个物品可以选无限次


2️⃣ 状态转移区别

dp[j] = max(dp[j], dp[j - w[i]] + v[i])

⚠️关键区别
j必须从小到大遍历,允许多次使用当前物品。


3️⃣ C++ 实现(完全背包)

#include<bits/stdc++.h>usingnamespacestd;intmain(){intn,W;cin>>n>>W;vector<int>w(n),v(n);for(inti=0;i<n;i++){cin>>w[i]>>v[i];}vector<int>dp(W+1,0);for(inti=0;i<n;i++){for(intj=w[i];j<=W;j++){dp[j]=max(dp[j],dp[j-w[i]]+v[i]);}}cout<<dp[W]<<endl;return0;}

四、多重背包问题

1️⃣ 问题描述

  • 每个物品最多只能选k[i]

2️⃣ 常见解决方法

✅ 方法一:暴力枚举(不推荐)

三重循环,时间复杂度高。

✅ 方法二:二进制拆分(推荐)

k个物品拆成:

1, 2, 4, ..., 剩余

然后转化为0/1 背包问题


3️⃣ C++ 实现(二进制优化)

#include<bits/stdc++.h>usingnamespacestd;intmain(){intn,W;cin>>n>>W;vector<int>dp(W+1,0);for(inti=0;i<n;i++){intw,v,k;cin>>w>>v>>k;for(intc=1;k>0;c<<=1){intnum=min(c,k);k-=num;intweight=num*w;intvalue=num*v;for(intj=W;j>=weight;j--){dp[j]=max(dp[j],dp[j-weight]+value);}}}cout<<dp[W]<<endl;return0;}

五、三种背包对比总结

类型每件物品j 遍历方向本质
0/1 背包最多 1 次从大到小防止重复选
完全背包无限次从小到大允许重复
多重背包有上限转化为 0/1二进制优化

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/23 16:12:32

13、UNIX用户管理全解析

UNIX用户管理全解析 1. 用户管理概述 用户管理几乎涉及系统管理各个领域的技能,工作核心围绕机器用户展开。理想的用户管理是不被用户察觉的,因为用户间接为系统运行付费,所以与系统的深入交互才得以实现。用户管理主要涉及用户ID的管理操作,包括添加、删除、修改、移动、…

作者头像 李华
网站建设 2026/8/24 4:05:39

动态规划01背包问题

动态规划:01背包问题 情景 现在有一个容量有限的背包(比如能装10公斤的东西)&#xff0c;现在有价值不同&#xff0c;重量也不同的几件物品&#xff0c;我们要怎样装才能让这个背包尽可能的装的价值最高 这就是为什么这个问题叫01背包问题&#xff0c;每个物品只有两种状态,放入…

作者头像 李华
网站建设 2026/8/23 21:56:42

WinForm DataGridView:单元格类型与高频绘制案例

目录 一、前置准备 二、DataGridView 常用单元格类型&#xff08;基础必掌握&#xff09; 1. 文本框单元格&#xff08;DataGridViewTextBoxColumn&#xff09; 2. 复选框单元格&#xff08;DataGridViewCheckBoxColumn&#xff09; 3. 下拉框单元格&#xff08;DataGridV…

作者头像 李华
网站建设 2026/8/24 14:04:05

java计算机毕业设计社区志愿者服务系统 智慧社区公益志愿协同平台 基层志愿者数字化运营管理系统

计算机毕业设计社区志愿者服务系统38q2o9 &#xff08;配套有源码 程序 mysql数据库 论文&#xff09; 本套源码可以在文本联xi,先看具体系统功能演示视频领取&#xff0c;可分享源码参考。当“志愿红”成为社区里最温暖的底色&#xff0c;传统的人工登记、微信群接龙、纸质工时…

作者头像 李华
网站建设 2026/8/25 18:52:57

考核算法题纠错

考核题算法题纠错 打家劫舍int rob(int* nums, int numsSize) {if (numsSize 0) return 0;if (numsSize 1) return nums[0];int prev_prev nums[0];int prev nums[0] > nums[1] ? nums[0] : nums[1];for (int i 2; i < numsSize; i) {int current prev > (prev…

作者头像 李华
网站建设 2026/8/24 11:15:53

天天劈砖休闲小游戏Linux演示教程

※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※ 本站教程、资源皆在单机环境进行&#xff0c;仅供单机研究学习使用。 ※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※ 一、获取材料和结果演示 百度网盘链接: https://…

作者头像 李华