背包九讲(求方案数,求具体方案数,有依赖背包)

news2024/12/29 8:56:38

文章目录

  • 求方案数
    • 基本思路
      • 代码
  • 背包问题求具体方案
    • 基本思路
      • 代码
  • 有依赖背包
    • 基本思路
      • 代码

求方案数

问题描述:
给定n nn个物品,以及一个容量大小为m mm的背包,然后给出n nn个物品的体积及价值,求背包最大价值是多少,也就是选择总体积不超过m mm的物品,然后使总价值最大。然后输出最优解的方案数。

基本思路

这是一个完全背包问题,可以使用动态规划来解决。

设dpi表示凑出体积为 i 的方案数,则有状态转移方程

边界条件为dp0=1因为背包体积为 0 时,不选任何物品即为一种方案。
最终答案即为 dpm表示凑出体积为 m 的方案数。
下面以一个样例来进行模拟解释:
假设给定物品体积数组为 v = [ 1 , 2 , 3 ]背包体积为 m = 5 则可以得到如下的状态转移方程:
在这里插入图片描述

代码

#include <iostream>
#include <vector>
using namespace std;

int main() {
    int n, m;
    cin >> n >> m;
    vector<int> v(n+1);
    for (int i = 1; i <= n; ++i) {
        cin >> v[i];
    }
    vector<int> dp(m+1);
    dp[0] = 1; // 背包体积为0时,方案数为1
    for (int i = 1; i <= n; ++i) {
        for (int j = v[i]; j <= m; ++j) {
            dp[j] += dp[j - v[i]];
        }
    }
    cout << dp[m] << endl; // 输出恰好凑出体积为m的方案数
    return 0;
}


背包问题求具体方案

题目描述:
给定n 个物品,以及一个容量大小为m 的背包,然后给出n个物品的体积及价值,求背包最大价值是多少,也就是选择总体积不超过m 的物品,然后使总价值最大。然后输出最优解的方案,并输出字典序最小的最优方案。

基本思路

注意,因为要求输出的顺序是按照字典序,故我们在进行 dp的过程中,枚举样本需要从大到小枚举,这样我们在按照字典序输出的时候就可以正向循环,查看状态 i是由哪个状态 j转移而来的 ( j > i )

代码

#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;

const int N = 1010;

int v[N], w[N];
int f[N][N];

int main()
{
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= n; i ++ ) cin >> v[i] >> w[i];
    
    for (int i = n; i >= 1; i -- )
        for (int j = 0; j <= m; j ++ )
        {
            f[i][j] = f[i + 1][j];
            if (j >= v[i]) f[i][j] = max(f[i][j], f[i + 1][j - v[i]] + w[i]);
        }
    
    int j = m;
    for (int i = 1; i <= n; i ++ )
        if (j >= v[i] && f[i][j] == f[i + 1][j - v[i]] + w[i])
        {
            cout << i << ' ';
            j -= v[i];
        }
        
    return 0;
}

有依赖背包

题目描述
有N 个物品和一个容量是V 的背包。物品之间具有依赖关系,且依赖关系组成一棵树的形状。如果选择一个物品,则必须选择它的父节点。
给出物品的体积、价值和依赖的物品编号,并保证所有物品组成一棵树,依赖的物品编号为-1则表示为根节点。

基本思路

有依赖关系的背包问题,他的每一个物品的选择情况都有其子节点的选择情况构成,而子节点的选择情况又由父节点决定(父节点如果不选,则所有子节点都选不了)。我们将每个父节点及其子节点看作是一个分组,父节点的情况由子节点所有选择情况中的一种构成,然后我们就成功的将该问题转化为了一道分组背包问题。

我们定义f[i][j]数组,i 表示节点,j 表示所占容量,那么f[i][j]就表示i节点在j 容量的情况下的最大价值。现在能和分组背包联系起来了吗?感觉没有关联也没问题,再接着往下看。在分组背包问题中,我们的第三维枚举决策的时候是枚举当前组里的物品,并且只能选一个物品。

而在此问题中,我们将每棵子树看作一个分组,将父节点的所有子节点的状态看作是组内的物品,枚举子节点所有选择情况所占体积,因为不同体积代表子节点的不同选择状态。然后我们从根节点开始递归到叶子节点,然后从叶子节点开始选择,每个节点的选择情况枚举完之后再返回到其父节点继续选择,最终返回到根节点进行选择。最后f[root][m]即为以root为根节点的树在容量为m情况下的最大价值。但需要注意,此时代表的时容量小于等于m的最大价值,同基础01背包一样,不是代表容量刚好为m时的最大价值。
在这里插入图片描述

代码

#include<iostream>
using namespace std;
int N,V,p,root;//N个物品V背包容量
int v[105],w[105];
int a[105][105],b[105],f[105][105];
//a[i][j]表示以i为头结点有j个子节点,a[i][j]则存的是下标,b[i]表示以i为根结点有b[i]个子节点
//f[i][j]表示以i为根节点,背包容量为j所获得的最大价值
void dfs(int t){//有树就要考虑遍历用dfs深搜,t表示此时父节点
//此时t为父节点,要想选下面的,前提就是把父节点选了,所以初始背包容量大于v[t]都初始化w[t]
    for(int i=v[t];i<=V;i++){
        f[t][i]=w[t];
    }
//下面不是一个父节点有许多子节点,按个遍历初始化它们,那么身为子节点又是父节点,又有子节点,递归下去
    for(int i=0;i<b[t];i++){
        int s=a[t][i];
        dfs(s);
        for(int j=V;j>=v[t];j--){//类似01背包逆序遍历
            for(int k=0;k<=j-v[t];k++){
                f[t][j]=max(f[t][j],f[t][j-k]+f[s][k]);//状态转移方程
                //f[t][j-k]+f[s][k]表示父节点要j-k的容量,子节点要k的容量
            }
        }
    }
}
int main(){
    cin>>N>>V;
    for(int i=1;i<=N;i++){
        cin>>v[i]>>w[i]>>p;
        if(p==-1){//-1表示为根节点
            root=i;
        }else{
            a[p][b[p]++]=i;//可以看一下上面a[i][j]与b[i]的含义
        }
    }
    dfs(root);
    cout<<f[root][V]<<endl;
    return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

递归排序 归并排序 快排

递归 求中点 midL(R-L)/2 midL((R-L)>>1)右移一位更快 子问题等量 mast er公式 T(N) a*T(N/b)O(N^d) T(N):母 T(N/b)&#xff1a;子 &#xff08;是否等量&#xff09; a&#xff1a;调用多少次 O(N^d)&#xff1a;除去子变量之外的时间复杂度 子问题等量 上面…

sqli-labs-master靶场通关

目录 一、sqli-labs第一关 1.判断是否存在sql注入 &#xff08;1&#xff09;提示输入数字值的ID作为参数&#xff0c;输入?id1 &#xff08;2&#xff09;通过数字值不同返回的内容也不同&#xff0c;所以我们输入的内容是带入到数据库里面查询了 &#xff08;3&#xff0…

信号量和管道

一、信号量 实现模拟售票问题&#xff1a; 1、信号量的机制&#xff1a;描述可使用资源的个数。 &#xff08;1&#xff09;P操作&#xff1a;表示使用这个资源&#xff0c;资源个数减一 逻辑&#xff1a;尝试获取资源——有资源可用直接使用 | 无资源可用等待 如果信号量的…

面向新人的 Java 面试问题(101-150)

101.什么是多态&#xff1f; 多态性被定义为能够采用多种形式的能力。它有两种类型&#xff0c;即编译时多态性或方法重载 - 在编译时调用的函数。例如&#xff0c;以“面积”类为例。根据参数数量&#xff0c;它可以计算正方形、三角形或圆形的面积。运行时多态性或方法覆盖 …

【详细】linux 打包QT程序

【详细】linux 打包QT程序 一. 安装linuxdeployqt1.1 下载linuxdeployqt源码并修改如下 二. 安装patchelf三. 打包appimage四. 打包成 Debian包4.1 control文件内容4.2 postinst文件内容4.3 postrm文件内容4.4 打包命令4.4 安装命令4.5 卸载命令 一. 安装linuxdeployqt 下载地…

【Redis】Redis 数据类型与结构—(二)

Redis 数据类型与结构 一、值的数据类型二、键值对数据结构三、集合数据操作效率 一、值的数据类型 Redis “快”取决于两方面&#xff0c;一方面&#xff0c;它是内存数据库&#xff0c;另一方面&#xff0c;则是高效的数据结构。 Redis 键值对中值的数据类型&#xff0c;也…

被极氪“背刺”新能源汽车车主,你可以说不

文 魏强 导语&#xff1a;谁也改变不了不断被“背刺”的命运。 8月13日晚&#xff0c;极氪召开发布会主推两款改款车——2025款极氪007升级了第二代金砖电池&#xff08;磷酸铁锂&#xff09;、标配了激光雷达和两颗Orin X芯片、全系降价2-3万元。2025款极氪001智驾芯片从Mob…

Artifactory集成LDAP示例

LDAP在企业软件身份认证中起到了非常关键的作用&#xff0c;给企业内用户带来了非常多的便利&#xff0c;JFrog 平台支持针对开箱即用的 LDAP 服务器对用户进行身份验证。下面我们一起看下Artifactory如何集成LDAP&#xff0c;本示例以OpenLDAP为例。 1.快速安装OpenLDAP doc…

SqlSugar详解-国产ORM框架

ORM (Object-Relational Mapping) 概念 ORM 是一种程序技术&#xff0c;用于将关系型数据库中的数据映射到对象上。 主要目的是简化数据库操作&#xff0c;使得开发人员可以像操作对象一样来操作数据库。 原理 数据表与类的映射&#xff1a;数据库中的表对应为类。 记录与对象…

灵办AI助手Chrome插件全面评测:PC Web端的智能办公利器

探索灵办AI助手在Mac OS上的高效表现&#xff0c;支持多款主流浏览器&#xff0c;助你轻松应对办公挑战 文章目录 探索灵办AI助手在Mac OS上的高效表现&#xff0c;支持多款主流浏览器&#xff0c;助你轻松应对办公挑战摘要引言开发环境介绍核心功能评测1. 网页翻译与双语对照 …

【祖孙询问】

问题 代码 #include <bits/stdc.h> using namespace std; const int N 4e410; vector<int> edge[N]; int p[N][20], d[N]; void dfs(int from, int u) {for(auto to : edge[u]){if(to from) continue;d[to] d[u] 1;p[to][0] u;dfs(u, to);}} void init() {fo…

mysql主从同步遇到的问题

1&#xff0c;主库data文件复制到从库&#xff0c;之后主库要同步的实例data一定不要在修改&#xff1b; 1.1&#xff0c;修改之后就要重新覆盖一遍 2&#xff0c;如果状态不对&#xff1a;一定要查看日志&#xff1b;比如slave_io_state是空时&#xff0c;需要查看日志 2.1&a…

使用百度文心智能体创建AI旅游助手

百度文心智能体平台为你开启。百度文心智能体平台&#xff0c;创建属于自己的智能体应用。百度文心智能体平台是百度旗下的智能AI平台&#xff0c;集成了先进的自然语言处理技术和人工智能技术&#xff0c;可以用来创建属于自己的智能体应用&#xff0c;访问官网链接&#xff1…

查看电脑连接过的wifi密码

netsh wlan show profiles netsh wlan show profile name"8821" keyclear

用Python实现9大回归算法详解——01. 线形回归算法

1. 线性回归的基本概念 线性回归是一种最基本的监督学习算法&#xff0c;用于预测因变量&#xff08;目标变量&#xff09;和一个或多个自变量&#xff08;特征变量&#xff09;之间的关系。线性回归假设因变量与自变量之间的关系是线性的&#xff0c;即可以用以下形式的线性方…

写一个githubDemo

1.List组件 <template><div class"container"><!-- 展示用户列表 --><div class"row"><divv-show"info.users.length"v-for"(item, index) in info.users":key"item.id"><div class"…

使用Python对知识文本进行分块

使用大型语言模型时&#xff0c;切勿忽略文本分块的重要性&#xff0c;其对处理结果的好坏有重大影响。接下来介绍常用的一些文本分块方法。1.1 一般的文本分块方法 如果不借助任何包&#xff0c;直接按限制长度切分方案。 text " 我是一个名为 chatGLm3-68 的人工智能助…

wps云字库字体下载到电脑

下拉字体菜单栏--->查看更多云字体 进入后 云字库里的字体&#xff0c;都只能在wps在线使用。 但是&#xff0c;要想下载到自己的电脑上&#xff0c;安装到电脑系统字体库中&#xff0c;WIN7的字体安装系统路径&#xff1a;C:\Windows\Fonts&#xff0c;以供电脑软件adobe …

Spring IoCDI(上)--初识

1. IoC & DI ⼊⻔ 1.1 Spring 是什么 通过前⾯的学习, 我们知道了Spring是⼀个开源框架, 他让我们的开发更加简单. 他⽀持⼴泛的应⽤场 景, 有着活跃⽽庞⼤的社区, 我们⽤⼀句更具体的话来概括Spring, 那就是: Spring 是包含了众多⼯具⽅法的 IoC 容器 1.1.1 什么是容器…

C#委托(入门)

1、语法 步骤 ①定义一个委托类型, 如Help ②委托类型实例化为委托实例 ③定义函数(与委托类型相匹配的) ④将函数交给委托实例使用 示例一 //方法一 void MyFunc1() {Console.WriteLine("Hello"); }//方法二 void MyFunc2() {Console.WriteLine("World&…