【自用】0-1背包问题与完全背包问题的Java实现

news2024/11/15 17:46:44

引言

背包问题是计算机科学领域的一个经典优化问题,分为多种类型,其中最常见的是0-1背包问题和完全背包问题。这两种问题的核心在于如何在有限的空间内最大化收益,但它们之间存在一些关键的区别:0-1背包问题允许每个物品只能选择一次,而完全背包问题则允许无限次选取同一物品。本篇博客将分别介绍这两个问题的动态规划解法,并附带相应的Java代码实现。

0-1背包问题

问题描述

假设你有一个背包,其最大承重能力为W千克,现在有一系列物品,每个物品有自己的重量Wi和价值Vi。你的任务是从这些物品中挑选一部分装入背包,使得背包的价值尽可能大,但不能超过背包的最大承重限制。

解决方案

我们可以采用动态规划的方法来求解这个问题。定义一个二维数组dp[i][j]表示从前i个物品中选择若干个放入容量为j的背包所能获得的最大价值。状态转移方程

Java代码实现

package dp;

import java.util.ArrayList;
import java.util.List;

public class Knapsack {
    public static void main(String[] args) {
        int n = 4; // 物品数量
        int bagweight = 16; // 背包最大容量
        int[] weight = {5, 7, 3, 4}; // 物品重量
        int[] value = {2, 5, 8, 1}; // 物品价值
        
        // 初始化 dp 数组
        int[][] dp = new int[n + 1][bagweight + 1];
        
        // 动态规划填充 dp 数组
        for (int i = 1; i <= n; i++) {
            for (int j = 0; j <= bagweight; j++) {
                if (j < weight[i - 1]) {
                    dp[i][j] = dp[i - 1][j]; // 不选择当前物品
                } else {
                    dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - weight[i - 1]] + value[i - 1]); // 选择或不选择当前物品
                }
            }
        }
        
        // 输出最大价值
        System.out.println("最大价值: " + dp[n][bagweight]);
        
        // 回溯找到具体的物品
        List<Integer> selectedItems = new ArrayList<>();
        int i = n, j = bagweight;
        while (i > 0 && j > 0) {
            if (dp[i][j] != dp[i - 1][j]) {
                selectedItems.add(i - 1); // 物品索引从0开始
                j -= weight[i - 1];
            }
            i--;
        }
        
        // 输出选择的物品
        System.out.print("选择的物品: ");
        for (int item : selectedItems) {
            System.out.print(item + " (重量: " + weight[item] + ", 价值: " + value[item] + ") ");
        }
        System.out.println();
    }
}

完全背包问题

问题描述

完全背包问题与0-1背包问题类似,不同之处在于每个物品的数量不限,即你可以无限制地选择同一个物品。

解决方案

对于完全背包问题,我们需要稍微修改一下状态转移方程。由于每个物品都可以多次选择,因此需要在循环中考虑是否要加入该物品到背包中。

  1. 状态表示

    • dp[i][j] 表示前 i 种物品放入容量为 j 的背包里任意取的最大价值。
  2. 确定边界和遍历顺序

    • 先遍历背包重量 (内层),再遍历物品 (外层循环)。
      for(int i=1;i<=n;i++) // 物品数量
          for(int j=1;j<=m;j++) // 背包容量
              if(j>=w[i]) // 判断是否能放得下第i件物品
                  dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i]); // 更新dp数组
              else 
                  dp[i][j]=dp[i-1][j]; // 不选第i件物品
  3. 找到状态转移方程

    • 状态转移方程是关键部分,它描述了如何从已知的状态推导出新的状态。
      dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]] + v[i])
    • 这意味着,对于每一件物品,可以选择放进去或者不放,比较两种情况下所能获得的最大价值。

Java代码实现

package dp;

import java.util.ArrayList;
import java.util.List;

public class AllPack {
    public static void main(String[] args) {
        int n = 3; // 物品数量
        int bagweight = 7; // 背包最大容量
        int[] weight = {3, 4, 2}; // 物品重量
        int[] value = {4, 5, 3}; // 物品价值
        
        // 初始化 dp 数组
        int[][] dp = new int[n + 1][bagweight + 1];
        
        // 动态规划填充 dp 数组
        for (int i = 1; i <= n; i++) {
            for (int j = 0; j <= bagweight; j++) {
                dp[i][j] = dp[i - 1][j]; // 不选择当前物品
                if (j >= weight[i - 1]) {
                    dp[i][j] = Math.max(dp[i][j], dp[i][j - weight[i - 1]] + value[i - 1]); // 选择或不选择当前物品
                }
            }
        }
        
        // 输出最大价值
        System.out.println("最大价值: " + dp[n][bagweight]);
        
        // 回溯找到具体的物品
        List<Integer> selectedItems = new ArrayList<>();
        int i = n, j = bagweight;
        while (i > 0 && j >= 0) {
            if (j >= weight[i - 1] && dp[i][j] != dp[i - 1][j]) {
                selectedItems.add(i - 1); // 物品索引从0开始
                j -= weight[i - 1];
            }
            i--;
        }
        
        // 输出选择的物品
        System.out.print("选择的物品: ");
        for (int item : selectedItems) {
            System.out.print(item + " (重量: " + weight[item] + ", 价值: " + value[item] + ") ");
        }
        System.out.println();
    }
}

  1. 0-1背包问题

    • 每个物品只能选择一次。
    • 回溯逻辑中,一旦确定选择了某个物品,就从当前的背包容量中减去该物品的重量,并且继续回溯下一个物品。
  2. 完全背包问题

    • 每个物品可以选择多次,直到背包容量不允许为止。
    • 回溯逻辑中,需要检查在当前背包容量下可以选择该物品的次数。这通常涉及到一个循环,直到背包容量不足以再添加一个该物品为止。

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

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

相关文章

Zookeeper的安装与使用

一、简介 1.1、概念 ZooKeeper 是一个开源的分布式协调服务&#xff0c;主要用于解决分布式系统中的数据一致性问题。它提供了一种可靠的机制来管理和协调分布式系统的各个节点。ZooKeeper 的设计目标是简化分布式应用的开发&#xff0c;提供简单易用的接口和高性能、高稳定性…

【模块一】kubernetes容器编排进阶实战之etcd的介绍与使用

etcd进阶 etcd简介&#xff1a;  etcd是CoreOS团队于2013年6月发起的开源项目&#xff0c;它的目标是构建一个高可用的分布式键值(key-value)数据库。etcd内部采用raft协议作为一致性算法&#xff0c;etcd基于Go语言实现。 官方网站&#xff1a;https://etcd.io/  gith…

【机器学习】如何配置anaconda环境(无脑版)

马上就要上机器学习的实验&#xff0c;这里想写一下我配置机器学习的anaconda环境的二三事 一、首先&#xff0c;下载安装包&#xff1a; Download Now | Anaconda 二、打开安装包&#xff0c;一直点NEXT进行安装 这里要记住你要下载安装的路径在哪&#xff0c;后续配置环境…

矩阵中的路径(dfs)-acwing

题目 23. 矩阵中的路径 - AcWing题库 代码 class Solution { public://以每一个坐标作为dfs起点bool hasPath(vector<vector<char>>& matrix, string str) {for (int i 0; i < matrix.size(); i )for (int j 0; j < matrix[i].size(); j )if (dfs(…

WEB攻防-通用漏洞SQL注入sqlmapOracleMongodbDB2等

SQL注入课程体系&#xff1a; 1、数据库注入-access mysql mssql oracle mongodb postgresql 2、数据类型注入-数字型 字符型 搜索型 加密型&#xff08;base64 json等&#xff09; 3、提交方式注入-get post cookie http头等 4、查询方式注入-查询 增加 删除 更新 堆叠等 …

android studio 更改gradle版本方法(备忘)

如果出现类似以下&#xff1a; Your build is currently configured to use Java 17.0.11 and Gradle 6.1.1. 或者类似&#xff1a; Failed to calculate the value of task ‘:app:compileDebugJavaWithJavac‘ property ‘options.generatedSo 消息时需要修改gradle版本&…

设计模式之装饰器模式(SSO单点登录功能扩展,增加拦截用户访问方法范围场景)

前言&#xff1a; 两个本想描述一样的意思的词&#xff0c;只因一字只差就让人觉得一个是好牛&#xff0c;一个好搞笑。往往我们去开发编程写代码时也经常将一些不恰当的用法用于业务需求实现中&#xff0c;但却不能意识到。一方面是由于编码不多缺少较大型项目的实践&#xff…

日志:中文 URI 参数乱码之 encodeURI、encodeURIComponent、escape 作为 Ajax 中文参数编码给 ASP 的记录

前面提到的了 ASP 输出 UTF-8 编码的中文不定时出现乱码的解决方案&#xff1a;ASP页面改为UTF-8编码后&#xff0c;刷新页面中文输入输出不定时乱码终极解决方案 今天遇到的则是输入 UTF-8 编码中文 URI 参数乱码的问题&#xff0c;第一次可以&#xff0c;刷新后取得的输入参…

Intern大模型训练营(八):Llamaindex RAG 实践

1. 基于 LlamaIndex 构建自己的 RAG 知识库 首先在Intern Studio中申请30% A100的开发机。 进入开发机后&#xff0c;创建新的conda环境&#xff0c;命名为 llamaindex&#xff0c;在命令行模式下运行&#xff1a; conda create -n llamaindex python3.10 复制完成后&#…

leetcode104:二叉树的最大深度

给定一个二叉树 root &#xff0c;返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;3示例 2&#xff1a; 输入&#xff1a;root [1,null,2] 输出…

Unity插件-Smart Inspector 免费的,接近虚幻引擎的蓝图Tab管理

习惯了虚幻的一张蓝图&#xff0c;关联所有Tab &#xff08;才发现Unity&#xff0c;的Component一直被人吐槽&#xff0c;但实际上是&#xff1a;本身结构Unity 的GameObject-Comp结构&#xff0c;是好的不能再好了&#xff0c;只是配上 smart Inspector就更清晰了&#xff0…

RDIFramework.NET CS敏捷开发框架 V6.1发布(.NET6+、Framework双引擎、全网唯一)

RDIFramework.NET C/S敏捷开发框架V6.1版本迎来重大更新与调整&#xff0c;全面重新设计业务逻辑代码&#xff0c;代码量减少一半以上&#xff0c;开发更加高效。全系统引入全新字体图标&#xff0c;整个界面焕然一新。底层引入最易上手的ORM框架SqlSugar&#xff0c;让开发更加…

运行springBlade项目历程

框架选择 官网地址&#xff1a;https://bladex.cn 使用手册&#xff1a;https://www.kancloud.cn/smallchill/blade 常见问题&#xff1a;https://sns.bladex.cn/article-14966.html 问答社区&#xff1a;https://sns.bladex.cn 环境配置 存在jdk8的情况下安装jdk17 jdk17gi…

图形 2.7 LDR与HDR

LDR与HDR B站视频&#xff1a;图形 2.7 LDR与HDR 文章目录 LDR与HDR基本概念LDRHDR为什么需要HDR不同显示屏的差异 Unity中的HDRCamera HDR 设置Lightmap HDR设置拾色器 HDR设置优缺点 HDR与Bloom通常Bloom渲染步骤渲染出原图获取图像中较亮部分高斯模糊叠加 Unity中Bloom渲染…

单片机设计智能翻译手势识别系统

目录 前言 一、本设计主要实现哪些很“开门”功能&#xff1f; 二、电路设计原理图 电路图采用Altium Designer进行设计&#xff1a; 三、实物设计图 四、程序源代码设计 五、获取资料内容 前言 在全球化的浪潮下&#xff0c;语言的多样性也为人们的交流带来了不小的挑战…

Python调用API翻译Excel中的英语句子并回填数据

一、问题描述 最近遇到一个把Excel表中两列单元格中的文本读取&#xff0c;然后翻译&#xff0c;再重新回填到单元格中的案例。大约有700多行&#xff0c;1400多个句子&#xff0c;一个个手动复制粘贴要花费不少时间&#xff0c;而且极易出错。这时&#xff0c;我们就可以请出…

TypeORM在Node.js中的应用

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 TypeORM在Node.js中的应用 TypeORM在Node.js中的应用 TypeORM在Node.js中的应用 引言 TypeORM 概述 定义与特点 发展历程 TypeO…

干货分享之Python爬虫与代理

嗨伙伴们&#xff0c;今天是干货分享哦&#xff0c;可千万不要错过。今天小蝌蚪教大家使用phthon时学会巧妙借用代理ip来更好地完成任务。 让我们先了解一下为什么说咱们要用爬虫代理ip呢&#xff0c;那是因为很多网站为了防止有人过度爬取数据&#xff0c;对自身资源造成损害…

腾讯云双11最强攻略:如何选购优惠产品,薅最划算的羊毛

目录 一、首选优惠产品 二、可参与拼团的产品&#xff1a;超值组合优惠 三、不推荐购买的产品 四、注意事项与优惠最大化技巧 总结 腾讯云的双11活动力度空前&#xff0c;适合个人开发者、中小企业甚至是大型公司。这份攻略将帮你了解该购买哪些产品&#xff0c;不该购买哪…

labview实现功能性全局变量

在日常的项目中&#xff0c;笔者最长使用的就是全局变量&#xff0c;这样用起来不仅省心省力&#xff0c;而且传值也很方便&#xff0c;没有什么阻碍&#xff0c;想要传什么数据一根线拉过去就可以了。后面才知道如果一直使用全局变量会导致读写卡死的状态&#xff0c;而且还有…