首页 > 其他分享 >关于分组背包的探究

关于分组背包的探究

时间:2025-01-19 19:42:55浏览次数:1  
标签:背包 weight int 组内 探究 分组 物品 dp

\(Problem\): 为什么分组背包只选同组内的一个数?

分组背包模版:点击查看代码
#include <iostream>
#include <vector>

using namespace std;

// 物品结构体,包含重量和价值
struct Item {
    int weight;
    int value;
    Item(int w, int v) : weight(w), value(v) {}
};

int main() {
    int N, V;  // N 表示物品组的数量,V 表示背包的容量
    cin >> N >> V;

    // 存储分组物品,每个分组是一个 Item 向量
    vector<vector<Item>> groups(N);  

    // 输入每个分组中的物品信息
    for (int i = 0; i < N; ++i) {
        int num;  // 该组内物品的数量
        cin >> num;
        for (int j = 0; j < num; ++j) {
            int w, v;  // 物品的重量和价值
            cin >> w >> v;
            groups[i].push_back(Item(w, v));
        }
    }

    // 二维数组用于动态规划,dp[i][j] 表示前 i 个物品组,背包容量为 j 时的最大价值
     int dp[1010][1010];
    for (int i = 1; i <= N; ++i) {
        for (int j = 0; j <= V; ++j) {
            dp[i][j] = dp[i - 1][j];  // 不选当前组的物品,直接继承上一组的结果
            // 遍历当前组内的物品
            for (const Item& item : groups[i - 1]) { 
                if (j >= item.weight) dp[i][j] = max(dp[i][j], dp[i - 1][j - item.weight] + item.value); 
            }
        }
    }
    cout << dp[N][V] << endl;  
    return 0;
}
点击查看答案

转移方程的形式

通常,我们采用动态规划来解决分组背包问题,其核心的状态转移方程大致形式如下(假设\(dp[i][j]\)表示前\(i\)个物品组,背包容量为\(j\)时能获得的最大价值):

\(cpp dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - k.weight] + k.value); \)

这里的\(k\)是遍历第\(i\)个物品组中的各个物品,\(k.weight\)表示物品的重量,\(k.value\)表示物品的价值。内层循环遍历第\(i\)组内的物品,去尝试更新\(dp[i][j]\)的值。

保证同组内只选一个的原理

  • 顺序依赖性:在进行动态规划的递推过程中,我们是按照物品组的顺序依次处理的,对于每一组物品,我们去考虑将组内的某个物品放入背包时,此时的状态依赖于没有选择该组内任何物品的状态(也就是 \(dp[i - 1][j]\) 这个状态)以及选择了该组内某个物品后剩余容量情况下的状态(\(dp[i - 1][j - k.weight] + k.value\))。由于我们是在遍历组内物品时,每次都是基于前\(i - 1\)组已经确定好的最优状态(即已经完成了前面组的选择情况计算)以及当前组内还未选择该物品时的状态来考虑是否选择当前物品,一旦选择了组内的某个物品进入背包,就相当于确定了这一组在当前背包容量下的选择,后续再去更新其他容量对应的状态时,不会再重复选择这组内已经选择过的物品或者再选择这组内的其他物品了。因为每次更新\(dp[i][j]\)都是基于前面组固定的情况以及当前组当前物品选择与否的情况来综合确定的,不会出现同一组内重复选择不同物品来更新同一个状态的情况。
  • 更新机制:转移方程的更新逻辑是在每一组物品的遍历中,针对当前背包容量\(j\),去尝试放入组内不同物品,看是否能得到更优的价值。它是一个“替换”或者“保持”已有最优值的过程,当我们通过选择组内某个物品更新了\(dp[i][j]\)的值后,这个值就代表了在考虑到第\(i\)组物品时,背包容量为\(j\)的当前最优情况,后续再去遍历组内其他物品时,只是去看能否通过选择其他物品来进一步优化这个状态,而不是去累加同组内多个物品的情况,所以自然就保证了同组内只会选择一个物品进入最终的背包方案来构成最优解。

标签:背包,weight,int,组内,探究,分组,物品,dp
From: https://www.cnblogs.com/FrankWKD/p/18679845

相关文章

  • MySQL——DQL基本查询 聚合函数 分组查询 排序查询 分页查询
    1.3DQL语法DQL:数据查询语言,用来查询数据库表中的记录。DQL基本查询1.查询多个字段select字段1,字段2,字段3...from表名;案例查询指定字段nameworknoageselectname,workno,agefromemp;2.查询所有字段select*from表名;select*fromemp;3.设置别名select字段1a......
  • 如何给一个下拉选项进行分组?
    在前端开发中,给下拉选项(通常使用<select>元素)进行分组通常是通过使用<optgroup>标签来实现的。<optgroup>标签用于对<select>元素中的<option>元素进行分组。你可以为每个<optgroup>标签设置label属性,以指定该组的标题。以下是一个简单的示例,展示如何使用<optgroup......
  • 怎样给radio分组呢?
    在前端开发中,给单选按钮(radiobuttons)分组是一个常见的需求。分组可以确保用户在同一组内只能选择一个选项。在HTML中,你可以使用name属性来给单选按钮分组。具有相同name属性的单选按钮将被视为同一组,用户只能选择其中的一个选项。以下是一个简单的示例,展示了如何使用name属性给......
  • 探究Java异常处理【保姆级教程】
    目录一、异常是什么,为啥要处理它二、Java异常体系概述三、Java异常处理方式1.try-catch-finally块2.throws关键字3.throw关键字四、自定义异常五、异常处理的最佳实践六、总结在Java编程的旅程中,异常处理就像是一位默默守护的卫士,时刻保障着程序的稳......
  • 线性dp+背包问题题解
    线性dp理解递推/记忆化搜索,有很多种理解方式递归重叠子问题的记忆化搜索:像这里例如\(f[3]\)可以通过一次计算得到,保存答案,下一次直接调用即可,省去很多复杂度我们从此引出dp第一个性质:最优子结构大问题的最优解包含小问题的最优解,并且小问题的最优解可以推导出大问题的最优......
  • 01背包的推导
    1.二维背包容量为7,总共有四件物品,价值和重量表示为{v,w},它们的价值和重量分别是1{2,3},2{5,5},3{1,1},4{9,3},求背包最多能装多少开始推导:能装i个物品并选取前i个物品,背包容量为j。dp[1][1]=0,显然是0,因为物品1的重量为3,你装答辩啊。dp[1][2]=0,容量不够还是不行。dp[1][3]=2,背包的容......
  • 【前端】自学基础算法 -- 25.动态规划-01背包问题
    动态规划-01背包问题简介动态规划(DynamicProgramming,简称DP)是一种解决复杂问题的方法,它将问题分解为更小、更简单的子问题,并存储这些子问题的解,以避免重复计算。动态规划通常用于优化问题,如求最大值、最小值或计数问题。动态规划的基本思想是将大问题分解为小问题,并从......
  • 零一背包
    [Algo]零一背包1.夏季特惠//1.夏季特惠//https://leetcode.cn/problems/tJau2o/description/longmaxHappyValue(vector<long>&a,vector<long>&b,vector<long>&w,longx){//a:原价数组,b:现价数组,w:快乐值数组,x:预算longn=a.size()......
  • 加密狗复制方法的探究
    在数字版权保护日益重要的今天,加密狗作为一种常见的硬件加密手段,被广泛应用于各类软件产品中,以防止软件被非法复制和使用。然而,在技术不断发展的背景下,对于加密狗复制方法的探讨也随之而来。一、硬件克隆方式芯片级克隆原理:这种方法是直接对加密狗内部的芯片进行分析和复制......
  • 代码随想录Day35 | 01背包问题 二维,01背包问题 一维,416.分割等和子集
    代码随想录Day35|01背包问题二维,01背包问题一维,416.分割等和子集01背包问题二维动态规划经典问题dp定义:dp[i][j]表示从下标为[0-i]的物品里任意取,放进容量为j的背包,价值总和最大是多少状态转移方程:dp[i][j]=max(dp[i-1][j],dp[i-1][j-weight[i]]+va......