分支限界法求解01背包(优先队列)【java】

news2025/2/6 0:51:04
实验内容:运用分支限界法解决0-1背包问题

实验目的:分支限界法按广度优先策略遍历问题的解空间树,在遍历过程中,对已经处理的每一个结点根据限界函数估算目标函数的可能取值,从中选取使目标函数取得极值的结点优先进行广度忧先搜索,从而不断调整搜索方向,尽快找到问题的解。因为限界函数常常是基于向题的目标函数而确定的,所以,分支限界法适用于求解最优化问题。本次实验利用分支限界法解决0-1背包问题。 

算法核心思想

  1. 首先对物品按照单位重量价值排序 
  2. 计算上界值
  3. 计算装入背包的真实价值bestvalue
  4. 使用优先队列存储活节点
  5. 根据bestvalue和重量进行剪枝
  6. 根据优先队列先出队的节点选择最接近最优的结果的情况

详细过程可参考文章:0-1背包问题-分支限界法(优先队列分支限界法)_0-1背包问题-优先队列式分支界限法的基础思想和核心步骤-CSDN博客

解空间树: 

 完整代码:

import java.util.PriorityQueue;
//排列树
class Node implements Comparable<Node> {
    int level; // 当前层级
    int weight; // 当前重量
    int value; // 当前价值
    int bound; // 上界

    public Node(int level, int weight, int value, int bound) {
        this.level = level;
        this.weight = weight;
        this.value = value;
        this.bound = bound;
    }

    @Override
    public int compareTo(Node other) {
        // 按照bound的降序排列
        return other.bound - this.bound;
    }
}

public class Knapsack {
    int capacity; // 背包容量
    int n; // 物品数量
    int[] weights; // 物品重量
    int[] values; // 物品价值
    int bestvalue;

    public Knapsack(int capacity, int n, int[] weights, int[] values) {
        this.capacity = capacity;
        this.n = n;
        this.weights = weights;
        this.values = values;
    }

    public int maxValue() {
        // 初始化优先队列
        PriorityQueue<Node> queue = new PriorityQueue<>();
        queue.add(new Node(0, 0, 0, bound(0, 0,0)));
        int maxValue = 0;
        this.bestvalue = 0;
        while (!queue.isEmpty()) {
            Node node = queue.poll(); // 取出队首元素--扩展节点
            if (node.level == n) { // 达到叶子节点,更新最大值
                maxValue = Math.max(maxValue, node.value);
            } else {
                // 左子树:选择当前物品
                if (node.weight + weights[node.level] <= capacity) {
                    int leftbound  = bound(node.level + 1, node.weight + weights[node.level] ,node.value + values[node.level]);
                    if(this.bestvalue<node.value + values[node.level]){
                        this.bestvalue = node.value + values[node.level];
                    }
                    if (leftbound<this.bestvalue){
                        continue;
                    }
                    queue.add(new Node(node.level + 1, node.weight + weights[node.level],
                            node.value + values[node.level],leftbound));
                }
                // 右子树:不选择当前物品
                int rightbound =bound(node.level + 1, node.weight,node.value);
                if (rightbound<this.bestvalue){
                    continue;
                }
                queue.add(new Node(node.level + 1, node.weight, node.value,rightbound));
            }
        }
        return maxValue;
    }

    // 计算上界函数
    private int bound(int i, int weight,int val) {
        int remainingWeight = capacity - weight; // 剩余重量
        int remainingValue = 0; // 剩余价值
        int j = i;
        for (; j < n; j++) {
            if (weights[j] > remainingWeight) { // 当前物品装不下,跳出循环
                break;
            }
            remainingWeight -= weights[j]; // 减去当前物品的重量
            remainingValue += values[j]; // 加上当前物品的价值
        }
        if (j<n){ //使用了double类型进行除法运算来保留小数部分的价值
            remainingValue = (int) (remainingValue + remainingWeight*(double)(values[j]/weights[j]));
        }
        return remainingValue+val;
    }


    public static void main(String[] args) {
        //int[] wt = {4,7,5,3};
        //int[] val = {40,42,25,12};
        //必须按照单位单位价值从大到小
        int[] wt = {4,1,1,2,12};
        int[] val = {10,2,1,2,4};
        int capacity = 15;
        int n = wt.length;
        Knapsack knapsack = new Knapsack(capacity,n,wt,val);
        int res = knapsack.maxValue();
        System.out.println(res);
    }
}

输出结果:15

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

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

相关文章

xxl-job报错:xxl-job registry fail:The access token is wrong

1、报错信息 .ExecutorRegistryThread : >>>>>>>>>>> xxl-job registry fail, registryParam:RegistryParam{registryGroupEXECUTOR, registryKeyxxl-job-executor-sample, registryValuehttp://192.168.133.1:9999/}, registryResult:Re…

支持二开可定制化的企业电子招标采购系统源码

随着企业的快速发展&#xff0c;招采管理逐渐成为企业运营中的重要环节。为了满足公司对内部招采管理提升的要求&#xff0c;建立一个公平、公开、公正的采购环境至关重要。在这个背景下&#xff0c;我们开发了一款电子招标采购软件&#xff0c;以最大限度地控制采购成本&#…

Pandas 数据处理入门

Python的Pandas库是数据科学家和分析师的神器。在本文中&#xff0c;我们将详细探讨如何利用Pandas进行有效的数据处理&#xff0c;包括数据结构的理解、数据的导入、探索和基本处理。 认识Pandas 简要介绍Pandas的重要性安装和导入Pandas库 import pandas as pdPandas数据结…

简单实现通过代码启动 appium server

一、前置说明 总体目录&#xff1a;《从 0-1 搭建企业级 APP 自动化测试框架》上节回顾&#xff1a;在 os_util 工具类和方法的实现 中&#xff0c;实现了启动应用程序和查杀进程的一些基本方法。本节目标&#xff1a;简单实现通过代码启动 appium server&#xff0c;代替手动…

【低照度图像增强系列(2)】Retinex(SSR/MSR/MSRCR)算法详解与代码实现

前言 ☀️ 在低照度场景下进行目标检测任务&#xff0c;常存在图像RGB特征信息少、提取特征困难、目标识别和定位精度低等问题&#xff0c;给检测带来一定的难度。 &#x1f33b;使用图像增强模块对原始图像进行画质提升&#xff0c;恢复各类图像信息&#xff0c;再使用目标检…

云仓酒庄的品牌雷盛红酒LEESON分享干红是纯葡萄酿造的吗?

干红是一种葡萄酒的简称&#xff0c;全称是干型红葡萄酒。葡萄酒按含残糖量分为干型、半干型、半甜型和甜型。无论什么型的酒&#xff0c;只要是葡萄酒&#xff0c;那就是葡萄酿造的。 云仓酒庄的品牌雷盛红酒LEESON分享干红是葡萄酒的一种&#xff0c;而葡萄酒却不止干红一种…

[问题随记]-如何修改网页中input type=file按钮名字

在使用HTML编辑网页的时候经常会出现如下问题&#xff0c;使用<input typefile>的类型控件上传文件按钮的时候&#xff0c;无法对按钮的名字进行修改&#xff0c;如下为解决方案 <input typefile nameBseleFile style"display:none" onchange"iTest.va…

【代码随想录】刷题笔记Day39

前言 下午答疑课过于无聊了&#xff0c;后台在跑代码也写不了作业&#xff0c;再刷点题吧~难得一天两篇 56. 合并区间 - 力扣&#xff08;LeetCode&#xff09; 和之前重叠区间是同个类型&#xff0c;和res里的元素比较&#xff0c;重叠就更新res里最后元素的最右边界 class…

JavaScript 中的双等号(==)和三等号(===)有何不同?何时使用它们?

​&#x1f308;个人主页&#xff1a;前端青山 &#x1f525;系列专栏&#xff1a;JavaScript篇 &#x1f516;人终将被年少不可得之物困其一生 依旧青山,本期给大家带来JavaScript篇专栏内容:JavaScript-等号区别 目录 和 区别&#xff0c;分别在什么情况使用 一、等于操作符…

Vue与低代码开发:简化前端开发的强力组合

在当下瞬息万变的软件开发领域&#xff0c;前端开发的速率与效益显得尤为关键。为适应市场的不断变迁&#xff0c;开发者们致力于寻求更为快捷、高效的开发模式。因此&#xff0c;Vue框架与低代码开发平台受到了开发者们的高度关注。本文旨在探讨Vue框架与低代码开发的融合&…

如何在水经微图中加载调用长光卫星影像

我们在这里&#xff0c;再来分享长光卫星影像在水经微图中的加载方法。 如何获取地图服务地址 如果你还没有在长光的官网注册&#xff0c;请通过以下地址注册。 https://www.jl1mall.com/rskit/?agentCompanySJZ&agentfangfang 因为&#xff0c;只有注册之后才能获取到…

嵌入式——I2C原理代码结合(干货)看图易懂

学习目标 理解I2C通讯原理理解I2C通讯过程中的信号理解软件I2C实现过程理解硬件I2C的工作内容学习内容 I2C通讯规则 I2C总线包括两根信号线:SDA(串行数据线)和SCL(串行时钟线)。这两根信号线共用一个总线,因此在总线上可以连接多个设备。在I2C总线上,每个设备都有一个唯…

【数据结构】查找与排序

要查询信息&#xff0c;涉及两个问题&#xff1a; 在哪里查&#xff1f;——查找表 怎么查&#xff1f;——查找方法 一.查找 1.查找表的定义&#xff1a; 查找表是由同类型的数据元素构成的集合 2.对查找表的基本操作&#xff1a; 1&#xff09;查询某个数据元素是否在查…

【原创分享】DDR拓扑结构的详细解析

在进行多片DDR设计的时候&#xff0c;通常DDR会存在拓扑结构&#xff0c;下面我们将详细介绍一下各种拓扑结构的区别以以及应用场景。 首先我们先介绍一下&#xff0c;当只存在一片DDR的时候通常是采用点对点的连接方式&#xff0c;点对点的布线方式优点是结构简单&#xff0c…

git之UGit可视化工具使用

一、下载安装UGit 链接&#xff1a;https://pan.baidu.com/s/1KGJvWkFL91neI6vAxjGAag?pwdsyq1 提取码&#xff1a;syq1 二 、使用SSH进行远程仓库连接 1.生成SSH密钥 由于我们的本地 git仓库和 gitee仓库之间的传输是通过SSH加密的&#xff0c;所以我们需要配置SSH公钥。才…

瓷片图绘制教程,R语言ggplot2绘图笔记

瓷片图像地板砖一样&#xff0c;由许多个小格子组成&#xff0c;不用的颜色深浅可以用来表示不同的值&#xff0c;横轴和纵轴可以用来展示不同的位置&#xff0c;二维码图、马赛克图、热图等都有异曲同工之妙。 今天分享一个在R语言中利用ggplot2包绘制瓷片图的方法&#xff0c…

处理器类型简介

转载自&#xff1a;https://www.cnblogs.com/zamely/p/4334979.html 多核处理器也称片上多核处理器&#xff08;Chip Multi-Processor&#xff0c;CMP&#xff09;。 1.多核处理器的流行 多核出现前&#xff0c;商业化处理器都致力于单核处理器的发展&#xff0c;其性能已经…

轻量封装WebGPU渲染系统示例<54>- 表现GLB模型之拱形门

当前示例源码github地址: https://github.com/vilyLei/voxwebgpu/blob/feature/material/src/voxgpu/sample/GLBMaterialTest.ts 当前示例运行效果: 此示例基于此渲染系统实现&#xff0c;当前示例TypeScript源码如下: export class GLBMaterialTest {private mRscene new …

java内存溢出初步排查

java内存模型 java内存空间主要包括以下几个部分&#xff1a;方法区、堆内存、虚拟机栈、本地方法栈 方法区&#xff1a;主要存放已被加载的类信息&#xff0c;常量&#xff0c;静态变量等。堆内存&#xff1a;Java堆是JVM所管理的最大一块内存空间&#xff0c;几乎所有的对象…

【ai】阿里云 大模型 api 聚合平台 dashscope

阿里云登录 - 欢迎登录阿里云&#xff0c;安全稳定的云计算服务平台 快速调用 前提条件 已开通服务并获得API-KEY&#xff1a;开通DashScope并创建API-KEY。 已安装最新版SDK&#xff1a;安装DashScope SDK。 DashScope灵积模型服务建立在“模型即服务”&#xff08;Model-a…