计算机算法分析与设计(20)---回溯法(0-1背包问题)

文章目录

    • 1. 题目描述
    • 2. 算法思路
    • 3. 例题分析
    • 4. 代码编写


1. 题目描述

 对于给定的 n n n 个物品,第 i i i 个物品的重量为 W i W_i Wi,价值为 V i V_i Vi,对于一个最多能装重量 c c c 的背包,应该如何选择放入包中的物品,使得包中物品的总价值最大?

2. 算法思路

 1. 将问题转化为:

在这里插入图片描述
 2. 按照上述思路,先将各物品按照单位价值递减的顺序排序,其次进行判断是否在承重范围值内。
 定义: c w cw cw(current weight)表示当前重量, c p cp cp(current price)表示当前价值。
 根节点代表扩展结点 ,其余每一层代表一个物品,越靠近根节点,单位价值越高。选中该物品,即搜索左子树,进行判断。具体执行操作如下所示:

 (1)先计算所有物品的单位价值,将其进行降序排列。

 (2)排列之后,从根节点(扩展节点)出发。

 (3)搜索左子树,判断是否满足约束条件(物品是否装入背包):

       若选中该物品(可行解),cw+=w[i],cp+=p[i],继续向下遍历;

       直至遇到不可行解时,开始向上回溯,取出最后一个装入的物品,进入右子树。

 (4)进入右子树,首先计算当前节点的上界bound(i):

       若bound(i)小于bestp,剪去右子树,继续向上回溯;
       
       否则进行步骤(3)。

 (5)遇到叶子节点,比较当前价值与bestp,若cp>bestp,则bestp进行更新。

 (6)直到遍历完所有的节点(除剪枝部分外)。

3. 例题分析

 1. 例题1(手写):

在这里插入图片描述
在这里插入图片描述
 2. 例题2:假设 n = 3 n=3 n=3(有三件物品),三个物品的重量为 20 、 15 、 10 {20、15、10} 201510,三个物品的价值为 20 、 30 、 25 {20、30、25} 203025,对于一个最大承重为 25 25 25 的背包,求包中物品的组合最大的价值是多少?

在这里插入图片描述
 3. 例题2分析过程:对三件物品分别进行编号 1 , 2 , 3 1,2,3 123。初始情况背包是空的。

 (1)首先我们把 1 1 1 号物品放进背包里,此时背包里只有一件物品,总重量为 0 + 20 = 20 0+20=20 0+20=20,没有超过承重 25 25 25,因此可以将 1 1 1 号物品成功放入背包内。

 (2)接下来尝试把 2 2 2 号物品放入背包内,但是发现包中 1 1 1 号物品和 2 2 2 号物品的重量和为 20 + 15 = 35 20+15=35 20+15=35,超过了承重 25 25 25,因此不能把 2 2 2 号物品放入背包内。

 (3)接着考虑 3 3 3 号物品,此时包中只有 1 1 1 号物品。发现 1 1 1 号物品和 3 3 3 号物品的重量和为 20 + 10 = 30 20+10=30 20+10=30,超过了承重 25 25 25,因此 3 3 3 号物品也不能放入背包内。

 (4)由于只有 3 3 3 件物品,并且对于每一种物品我们都考虑过是否将其放入背包内,也就是找到了一种基本情况。找到一个基本情况后,我们就可以看看包里的物品的总价值了。这里包里只有一个 1 1 1 号物品,因此总价值为 20 20 20

 (5)重点来了!回溯过程:每次找出一种满足条件的基本情况就进行一次回溯,找到最后放入包中的物品并将其取出,接着考虑是否放入编号在这个物品之后的第一个物品。这里我们就把 1 1 1 号物品取出,接下来考虑是否放入 2 2 2 号物品。

 (6)取出 1 1 1 号物品后背包是空的,此时如果放入 2 2 2 号物品,背包总重量为 15 15 15,没有超过背包承重,因此把 2 2 2 号物品放入背包内。

 (7)类似地,考虑将 3 3 3 号物品放入背包内。由于 2 2 2 号物品和 3 3 3 号物品的重量和为 15 + 10 = 25 15+10=25 15+10=25,没有超过承重 25 25 25,因此将其放入背包内。

 (8)由于考虑完了 3 3 3 号物品,因此又找到了一个基本情况,记下此时包里物品的总价值,为 30 + 25 = 55 30+25=55 30+25=55。由于 55 55 55 高于上一种基本情况的总价值,因此将最优解更新为 55 55 55

 (9)进行一次回溯,取出背包中最后放入的物品,也就是 3 3 3 号物品。但是注意:当最后放入背包中的物品恰好是编号最大的物品时,需要额外进行一次回溯。为什么呢?因为编号最大的物品之后已经没有编号更大的物品了,因此没有可以考虑的下一种情况,只能在上一个层面上在进行一次回溯才能产生可能的最优解(此处不必考虑只放入2号物品的情况,因为一定不是最优解,原因可以自己思考一下)。 这里再回溯一次,也就是将倒数第二个放入包中的物品取出来,这里就取出 2 2 2 号物品。先后取出 3 3 3 号物品和 2 2 2 号物品之后包应该处于空的状态。

 (10)上一步中取出了 2 2 2 号物品,因此这一步直接考虑能否放入 3 3 3 号物品,简单的判断后即可得出可以放入,并且同上理也可以得出这是一种基本情况。但是由于包中只有 3 3 3 号物品,总价值为 25 25 25,没有超过当前的最优解 55 55 55,因此将该情况忽略。

 (11)最后一次回溯,取出包中的 3 3 3 号元素。由于此时包已经空了,并且最后一次取出的是编号最大的元素,那么说明算法已经完成了所有情况的遍历,算法终止, 55 55 55 是最优解。

4. 代码编写

// n=5, c=10, w={2, 2, 6, 5, 4}, v={6, 3, 5, 4, 6}的0-1背包问题的最优解和最优值。
#include <iostream>
using namespace std;
 
#define N 10
int w[N]; //重量
int v[N]; //价值
int x[N]; //1表放入背包,0表不放入
int n,c;  //n:物品个数 c:背包的最大容量
 
int cw=0; //当前物品总重
int cv=0; //当前物品总价值
 
int bestp=0;  //当前最大价值
int bestx[N]; //最优解
 
//回溯函数 k表示当前处在第几层做选择,k=1时表示决定是否将第一个物品放入背包
void backtrack(int k)
{//叶子节点,输出结果
   if(k>n)
   {
   //找到一个更优的解
     if(cv>bestp)
	 {  //保存更优的值和解
        bestp = cv;
        for(int i=1; i<=n; i++)
            bestx[i] = x[i];
     }
    }
   else
   {//遍历当前节点的子节点
     for(int i=0; i<=1; i++)
	 {
        x[k]=i;
        if(i==0)
		{
            backtrack(k+1);
        }
        else
		{  //约束条件:当前物品是否放的下
           if((cw+w[k])<=c)
		   {
             cw += w[k];
             cv += v[k];
             backtrack(k+1);
             cw -= w[k];
             cv -= v[k];
           }
        }
     }
  }
}
 
int main()
{
 
    cout<<"请输入物品的个数:";
    cin>>n;
    cout<<"请输入每个物品的重量及价值:"<<endl;
    for(int i=1;i<=n;i++)
    {
        cin>>w[i]>>v[i];
    }
    cout<<"请输入背包的限制容量:";
    cin>>c;
    backtrack(1);
    cout<<"最优值是:"<<bestp<<endl;
    cout<<"(";
    for(int i=1;i<=n;i++)
    {
    	cout<<bestx[i]<<" ";
	} 
    cout<<")";
    return 0;
}

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

轻量级导出 Excel 标准格式

一般业务系统中都有导出到 Excel 功能&#xff0c;其实质就是把数据库里面一条条记录转换到 Excel 文件上。Java 常用的第三方类库有 Apache POI 和阿里巴巴开源的 EasyExcel 等。另外也有通过 Web 模板技术渲染 Excel 文件导出&#xff0c;这实质是 MVC 模式的延伸&#xff0c…

React环境初始化

环境初始化 学习目标&#xff1a; 能够独立使用React脚手架创建一个React项目 1.使用脚手架创建项目 官方文档&#xff1a;(https://create-react-app.bootcss.com/)    - 打开命令行窗口    - 执行命令      npx create-react-app projectName    说明&#xff1a…

智安网络|探索语音合成技术的未来:揭秘人工智能配音技术的背后

随着人工智能技术的迅猛发展&#xff0c;配音行业也迎来了人工智能配音技术的崭新时代。人工智能配音技术通过语音合成和自然语言处理等技术手段&#xff0c;实现了逼真的语音合成&#xff0c;为影视、广告和游戏等领域带来了新的可能性。 第一部分&#xff1a;语音合成技术的…

天锐绿盾加密软件——企业数据透明加密、防泄露系统

天锐绿盾是一种企业级数据透明加密、防泄密系统&#xff0c;旨在保护企业的核心数据&#xff0c;防止数据泄露和恶意攻击。它采用内核级透明加密技术&#xff0c;可以在不影响员工正常工作的前提下&#xff0c;对需要保护的数据进行加密操作。 PC访问地址&#xff1a; https:/…

linux安装visual studio code

下载 https://code.visualstudio.com/ 下载.deb文件 安装 假如文件被下载到了 /opt目录下 进入Opt目录&#xff0c;右键从当前目录打开终端。 输入下面的安装命令。 sudo apt-get install ./code_1.83.1-1696982868_amd64.deb 安装成功。 配置 打开 visual studio cod…

宏集案例 | Panarama SCADA平台在风电场测量的应用,实现风电场的高效管理!

文章来源&#xff1a;宏集工业物联网 阅读原文&#xff1a;https://mp.weixin.qq.com/s/MLYhBWiWx7qQSApx_3xhmA 宏集Panorama SCADA平台在风电场测量的应用 宏集方案 01应用背景 随着煤碳、石油等能源的逐渐枯竭&#xff0c;人类越来越重视可再生能源的利用。风能作为一种…

小知识(5) el-table行样式失效问题

一、实现效果 子级呈现不同颜色去区分 二、最初代码 tips: 我这里使用的vue3 elementplus <el-table :row-class-name"tableRowClassName" >... </el-table>function tableRowClassName({ row, rowIndex }) {if (row.children.length 0) {return …

上海市道路数据,有63550条数据(shp格式和xlsx格式)

数据地址&#xff1a; 上海市道路https://www.xcitybox.com/datamarketview/#/Productpage?id391 基本信息. 数据名称: 上海市道路数据 数据格式: Shpxlsx 数据时间: 2020年 数据几何类型: 线 数据坐标系: WGS84坐标系 数据来源&#xff1a;网络公开数据 数据字段&am…

k8s-----19、Helm

Helm 1、引入2、概述2.1 重点2.2 V3版本的Helm2.2.1 与之前版本的不同之处2.2.2 V3版本的运行流程 3、安装和配置仓库、一些附带操作3.1 安装3.2 配置仓库3.3 常用命令3.4 添加helm的自动补齐 4、快速部署应用(weave应用)5、 自行创建Chart5.1 Chart目录内容解析5.2 简单安装部…

Pytorch指定数据加载器使用子进程

torch.utils.data.DataLoader(train_dataset, batch_sizebatch_size, shuffleTrue,num_workers4, pin_memoryTrue) num_workers 参数是 DataLoader 类的一个参数&#xff0c;它指定了数据加载器使用的子进程数量。通过增加 num_workers 的数量&#xff0c;可以并行地读取和预处…

maven-default-http-blocker (http://0.0.0.0/): Blocked mirror for repositories

前言 略 说明 新设备上安装了mvn 3.8.5&#xff0c;编译新项目出错&#xff1a; [ERROR] Non-resolvable parent POM for com.admin.project:1.0: Could not transfer artifact com.extend.parent:pom:1.6.9 from/to maven-default-http-blocker (http://0.0.0.0/): Bl…

建联合作1000+达人,如何高效管理?

随着社交媒体的发展&#xff0c;达人营销已成为品牌营销重要的方式之一&#xff0c;甚至可以说是必选项。 对于很多品牌商家来说&#xff0c;一次合作几百个不同类型、不同社媒平台的达人&#xff0c;已屡见不鲜。在电商大促前、主推单品爆品时&#xff0c;同时合作上千个达人&…

jenkins实践篇(1)——基于分支的自动发布

问题背景 想起初来公司时&#xff0c;我们还是在发布机上直接执行发布脚本来运行和部署服务&#xff0c;并且正式环境和测试环境的脚本都在一起&#xff0c;直接手动操作脚本时存在比较大的风险就是将环境部署错误&#xff0c;并且当时脚本部署逻辑还没有检测机制&#xff0c;…

vscode Coder Runner 运行C++

1. 设置Code Runner 2. 防止输入读不到&#xff0c;把在终端运行勾上。 3. 设置minw/bin的环境变量 安装mingw教程&#xff1a;https://blog.csdn.net/fancy_male/article/details/133992000 4. 见图

数据结构:选择题+编程题(每日一练)

目录 选择题&#xff1a; 题一&#xff1a; 题二&#xff1a; 题三&#xff1a; 题四&#xff1a; 题五&#xff1a; 编程题&#xff1a; 题一&#xff1a;单值二叉树 思路一&#xff1a; 题二&#xff1a;二叉树的最大深度 思路一&#xff1a; 本人实力有限可能对…

Go学习第八章——面向“对象”编程(结构体与方法)

Go面向“对象”编程&#xff08;结构体与方法&#xff09; 1 结构体1.1 快速入门1.2 内存解析1.3 创建结构体四种方法1.4 注意事项和使用细节 2 方法2.1 方法的声明和调用2.2 快速入门案例2.3 调用机制和传参原理2.4 注意事项和细节2.5 方法和函数区别 3 工厂模式 Golang语言面…

服装服饰小程序商城的作用是什么

随着数字化转型节奏加快&#xff0c;各个行业都在加紧线上平台渠道的建设&#xff0c;而对于服装业来讲&#xff0c;在线商城无疑是**的选择&#xff0c;一方面可以去除平台的限制&#xff0c;摆脱佣金烦恼&#xff0c;还可搭建自有会员体系、私域流量池&#xff0c;持续转化变…

使用ruoyi框架遇到的问题修改记录

使用ruoyi框架遇到的问题修改记录 文章目录 使用ruoyi框架遇到的问题修改记录上传后文件名改变上传时设置单多文件及其他选项附件显示文件名&#xff0c;点击下载附件直接显示图片表格固定列查询数据库作为下拉选项值字典使用加入json递归注解&#xff0c;防止无限递归内存溢出…

从零开始学习wpsjs

1.这是一个简单的wpsjs学习文档&#xff0c;我是边学习wpsjs边记录学习的&#xff0c;希望对您的学习有所帮助 开发事项&#xff1a; 全局安装wpsjs:npm install -g wpsjsWpsjs create HelloWps 安装wps npm install -g wpsjs 新建一个wps加载项 输入命令wpsjs create HelloW…