【回溯】0-1背包Python实现

news2024/11/17 3:24:50

文章目录

    • @[toc]
      • 问题描述
        • 形式化描述
      • 回溯法
      • 时间复杂性
      • `Python`实现

因上努力

个人主页:丷从心

系列专栏:回溯法

果上随缘


问题描述

  • 给定 n n n种物品和一背包,物品 i i i的重量是 w i w_{i} wi,其价值为 v i v_{i} vi,背包的容量为 c c c
  • 如何选择装入背包中的物品,使得装入背包中物品的总价值最大
形式化描述
  • 给定 c > 0 c > 0 c>0 w i > 0 w_{i} > 0 wi>0 v i > 0 ( 1 ≤ i ≤ n ) v_{i} > 0 (1 \leq i \leq n) vi>0(1in),找出一个 n n n 0 − 1 0-1 01向量 ( x 1 , x 2 , ⋯   , x n ) (x_{1} , x_{2} , \cdots , x_{n}) (x1,x2,,xn) x i ∈ {   0 , 1   } ( 1 ≤ i ≤ n ) x_{i} \in \set{0 , 1} (1 \leq i \leq n) xi{0,1}(1in),使得 ∑ i = 1 n w i x i ≤ c \displaystyle\sum\limits_{i = 1}^{n}{w_{i} x_{i}} \leq c i=1nwixic,而且 ∑ i = 1 n v i x i \displaystyle\sum\limits_{i = 1}^{n}{v_{i} x_{i}} i=1nvixi达到最大
  • 0 − 1 0-1 01背包问题是一个特殊的整数规划问题

max ⁡ ∑ i = 1 n v i x i { ∑ i = 1 n w i x i ≤ c x i ∈ {   0 , 1   } ( 1 ≤ i ≤ n ) \max\displaystyle\sum\limits_{i = 1}^{n}{v_{i} x_{i}} \kern{2em} \begin{cases} \displaystyle\sum\limits_{i = 1}^{n}{w_{i} x_{i} \leq c} \\ x_{i} \in \set{0 , 1} (1 \leq i \leq n) \end{cases} maxi=1nvixi i=1nwixicxi{0,1}(1in)


回溯法

  • 0 − 1 0-1 01背包问题是子集选取问题,解空间可用子集树表示,解 0 − 1 0-1 01背包问题的回溯法与解装载问题的回溯法十分相似
  • 在搜索解空间树时,只要其左儿子结点是一个可行结点,搜索就进入其左儿子,当右子树中有可能包含最优解时才进入右子树搜索,否则将右子树剪去
  • r r r是当前剩余物品价值总和, c p cp cp是当前价值, b e s t p bestp bestp是当前最优价值,当 c p + r ≤ b e s t p cp + r \leq bestp cp+rbestp时,可剪去右子树,计算右子树中解的上界的更好方法是,将剩余物品以其重量价值排序,然后依次装入物品,直至装不下时,再装入该物品的一部分而装满背包,由此得到的价值是右子树中解的上界
  • 为了便于计算上界,可先将物品依其单位重量价值从大到小排序,此后只要按顺序考察各物品即可

时间复杂性

  • 计算上界需要 O ( n ) O(n) O(n)时间,在最坏情况下有 O ( 2 n ) O(2^{n}) O(2n)个右儿子结点需要计算上界
  • 所以解 0 − 1 0-1 01背包问题的回溯算法所需的计算时间为 O ( n 2 n ) O(n 2^{n}) O(n2n)

Python实现

def backtrack_knapsack(values, weights, capacity):
    n = len(values)
    # 计算物品的单位重量价值
    unit_values = [v / w for v, w in zip(values, weights)]
    # 根据单位重量价值对物品进行降序排序
    sorted_items = sorted(range(n), key=lambda k: unit_values[k], reverse=True)

    best_solution = []
    best_value = 0

    def constraint(weight):
        # 约束函数: 检查当前解是否满足容量限制
        return weight <= capacity

    def bound(weight, value, index):
        # 限界函数: 计算当前解的价值总和加上剩余物品价值作为上界, 用于剪枝
        bound = value
        remaining_capacity = capacity - weight

        for item in range(index + 1, n):
            if remaining_capacity >= weights[sorted_items[item]]:
                remaining_capacity -= weights[sorted_items[item]]
                bound += values[sorted_items[item]]
            else:
                bound += remaining_capacity * values[sorted_items[item]] / weights[sorted_items[item]]

                break

        return bound

    def backtrack(solution, weight, value, index):
        nonlocal best_solution, best_value

        if index == n:
            # 已经遍历完所有物品
            if value > best_value:
                # 如果当前解的价值更大, 更新最优解
                best_solution = solution
                best_value = value

            return

        # 尝试选择当前物品
        weight += weights[sorted_items[index]]
        value += values[sorted_items[index]]

        if constraint(weight):
            # 如果满足约束函数, 继续探索下一个物品
            backtrack(solution + [1], weight, value, index + 1)

        # 恢复回溯之前状态
        weight -= weights[sorted_items[index]]
        value -= values[sorted_items[index]]

        # 尝试不选择当前物品
        if bound(weight, value, index) >= best_value:
            # 如果当前解的上界仍然可能更好, 继续探索下一个物品
            backtrack(solution + [0], weight, value, index + 1)

    backtrack([], 0, 0, 0)

    return best_solution, best_value


values = [60, 100, 120]
weights = [10, 20, 30]
capacity = 50

best_solution, best_value = backtrack_knapsack(values, weights, capacity)

print(f'最优解: {best_solution}')
print(f'最优值: {best_value}')
最优解: [0, 1, 1]
最优值: 220

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

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

相关文章

第27关 在K8s集群上使用Helm3部署最新版本v2.10.0的私有镜像仓库Harbor

------> 课程视频同步分享在今日头条和B站 大家好&#xff0c;我是博哥爱运维。 在前面的几十关里面&#xff0c;博哥在k8s上部署服务一直都是用的docker hub上的公有镜像&#xff0c;对于企业服务来说&#xff0c;有些我们是不想把服务镜像放在公网上面的&#xff1b; 同时…

记一次史诗级灾难的恢复方法:笨蛋edge把我收藏夹清空了

先在文件管理器中打开隐藏文件和文件扩展名的按钮 这一点可以去网上搜搜&#xff0c;教程非常多。 打开edge&#xff0c;关闭收藏夹的同步按钮 根据下图所示路径找到文件 Bookmarks 15060是我的用户名&#xff0c;各位要找到以自己的用户名命令的文件夹哈。 按顺序执行&…

金三银四,软件测试面试题总结,offer稳稳的。。。

前言 前面看到了一些面试题&#xff0c;总感觉会用得到&#xff0c;但是看一遍又记不住&#xff0c;所以我把面试题都整合在一起&#xff0c;都是来自各路大佬的分享&#xff0c;为了方便以后自己需要的时候刷一刷&#xff0c;不用再到处找题&#xff0c;今天把自己整理的这些…

【AI】计算机视觉VIT文章(Transformer)源码解析

论文&#xff1a;Dosovitskiy A, Beyer L, Kolesnikov A, et al. An image is worth 16x16 words: Transformers for image recognition at scale[J]. arXiv preprint arXiv:2010.11929, 2020 源码的Pytorch版&#xff1a;https://github.com/lucidrains/vit-pytorch 0.前言 …

绝缘电阻测试仪的测量范围有多少?它的测量方法是什么?

绝缘电阻测试仪广泛应用于设备检测和故障排除。它广泛应用于电力检测行业。甚至可以说&#xff0c;电力设备离不开绝缘电阻测试仪设备。对于许多经验丰富的电力测试工人来说&#xff0c;绝缘电阻测试仪的常规测量范围和方法应该非常清楚。在本文中&#xff0c;我们将向一些新的…

分享免费视频素材网站,第三弹

今天继续给大家分享免费视频素材网站&#xff0c;整理不易&#xff0c;觉得内容不错的话&#xff0c;可以点赞收藏一下哦&#xff5e; 1.livelybg 一个免费视频素材小站&#xff0c;资源很少很少&#xff0c;但均为很少见的科幻、超现实、赛博朋克风格素材&#xff01;&#xf…

Linux账号和权限管理

目录 前言 一、管理用户账号 1、Linux系统中用户账号类型 2、用户标识UID的分类 3、用户账号文件 4、用户账号的初始配置文件 5、用户账号的管理命令 5.1 useradd 5.2 usermod 5.3 passwd 5.4 userdel 二、管理组账号 1、Linux系统中组账号类型 2、组标识号GID的…

blackbox黑盒监控部署(k8s内)tensuns专用

一、前言 部署在k8s中需要用到deployment、configmap、service服务 二、部署 创建存放yaml的目录 mkdir /opt/blackbox-exporter && cd /opt/blackbox-exporter 编辑blackbox配置文件&#xff0c;使用configmap挂在这 vi configmap.yaml apiVersion: v1 kind: Confi…

移动app软件开发50个创意

那些需要努力工作才能赚钱的日子已经一去不复返了。现在&#xff0c;可以通过软件app赚钱。好吧&#xff0c;人类完全依赖智能手机这并不是谎言&#xff0c;无论是订购项目还是呼叫某人提供各种服务。因此&#xff0c;投资移动软件app开发是一个好主意。然而&#xff0c;移动软…

【51单片机系列】DS1302时钟模块

本文是关于DS1302时钟芯片的相关介绍。 文章目录 一、 DS1302时钟芯片介绍二、DS1302的使用2.1、DS1302的控制寄存器2.2、DS1302的日历/时钟寄存器2.3、片内RAM2.4、DS1302的读写时序 三、SPI总线介绍四、DS1302使用示例 一、 DS1302时钟芯片介绍 DS1302是DALLAS公司推出的涓流…

【教程】使用ipagurd打包与混淆Cocos2d-x的Lua脚本

文章目录 摘要引言正文1. 准备工作2. 使用ipaguard处理Lua文件3. 运行ipagurd进行混淆代码加密具体步骤测试和配置阶段IPA 重签名操作步骤4. IPA重签名与发布 总结 摘要 本文将介绍如何使用ipagurd工具对Cocos2d-x中的Lua脚本进行打包与混淆&#xff0c;以及在iOS应用开发中的…

IDEA2023创建web项目

一、新建项目 点击File->New->Project...&#xff0c;如果是第一次创建项目则单击New Project 二、添加Web Application 建好的样子 把web移动到main目录下同时改名为webapp 三、不存在Add Framework Support添加Web Application 如何存在Add Framework Support&#…

React快速入门之交互性

响应事件 创建事件处理函数 处理函数名常以handle事件名命名 function handlePlayClick() {alert(Playing);}传递事件处理函数 函数名、匿名两种方式&#xff01; function PlayButton() {function handlePlayClick() {alert(Playing);}return (<Button handleClick{handl…

信息科技成“新课标”重点,家长必须要懂!

日新月异的当下&#xff0c;人工智能无疑是与生活最为密切相关的核心词语。或许在不远的将来&#xff0c;技术含量低的重复性工作将会被机器取代。甚至有人认为&#xff0c;现在的小学生&#xff0c;大概多数会在未来从事目前尚未发明出来的工作。 近年来&#xff0c;我国的教…

微信消息撤回拦截:x64dbg反汇编实现揭秘

在数字世界中&#xff0c;信息传递的速度快如闪电&#xff0c;但也常常伴随着一些遗憾。微信作为我们日常生活中最常用的通讯工具之一&#xff0c;其撤回功能让许多人在发出信息后有了后悔的机会。然而&#xff0c;有时候我们却希望能够拦截这些即将被撤回的信息。通过x64dbg反…

YOLOv7+Pose姿态估计+tensort部署加速

YOLOv7是一种基于深度学习的目标检测算法&#xff0c;它能够在图像中准确识别出不同目标的位置和分类。而姿态估计pose和tensort则是一种用于实现人体姿态估计的算法&#xff0c;可以对人体的关节位置和方向进行精准的检测和跟踪。 下面我将分点阐述YOLOv7姿态估计posetensort…

用 Unity 实现的安检模拟小游戏源码,通过安检设备 (扫描仪) 检查乘客的随身物品 根据禁止名单对乘客做出判断是否允许通行

介绍 用 Unity 实现的安检模拟小游戏 软件版本 Unity 2019.4.9f1 (64-bit) Visual Studio 2019 游戏玩法 在游戏中你将扮演一名安全检查员 通过安检设备 (扫描仪) 检查每位乘客的随身物品 根据禁止名单对乘客做出判断&#xff1a;允许通行或者下令逮捕 游戏效果 游戏截图…

maven工具的搭建以及使用

文章目录 &#x1f412;个人主页&#x1f3c5;JavaEE系列专栏&#x1f4d6;前言&#xff1a;&#x1f380;首先进行maven工具的搭建&#x1f993;1.[打开下载 maven 服务器官网](http://maven.apache.org)&#x1fa85;2.解压之后&#xff0c;配置环境变量&#x1f3e8;3.打开设…

【SAM系列】I-MedSAM: Implicit Medical Image Segmentation with Segment Anything

论文链接&#xff1a;https://arxiv.org/abs/2311.17081 比较有趣的点&#xff1a;frequency adapter

数据结构课设迷宫问题

迷宫问题 【问题描述】以一个mn的长方阵表示迷宫&#xff0c;0和1分别表示迷宫中的通路和障碍。设计一个程序&#xff0c;对任意设定的迷宫&#xff0c;求出一条从入口到出口的通路&#xff0c;或得出没有通路的结论。 【基本要求】编写一个求解迷宫的非递归程序。求得的通路…