跟着ChatGPT学算法-完全背包问题

news/2024/9/26 1:15:42

一、题目

给定 n 个物品,第 i 个物品的重量为 wgt[i-1]、价值为 val[i-1] ,和一个容量为 cap 的背包。每个物品可以重复选取,问在限定背包容量下能放入物品的最大价值。

 

二、和ChatGPT聊聊

您是一位资深算法工程师,请深入浅出地给出完全背包问题的分析过程和完整带注释的Java代码实现

 

GPT-4-Turbo

 完全背包问题是动态规划中的一个经典问题,与0-1背包问题相似,但在完全背包问题中,每种物品可以被无限次选取。这个问题的目标是在不超过背包容量的前提下,最大化背包中物品的总价值
 

分析过程

  1. 定义状态:定义 dp[i][c] 为考虑前 i 个物品,当背包容量为 c 时能达到的最大价值。

  2. 状态转移方程:dp[i][c] = max(dp[i-1][c], dp[i][c-wgt[i-1]] + val[i-1])

    • 如果不选当前物品 i,则 dp[i][c] = dp[i-1][c],直接继承前一个状态的值。
    • 如果选当前物品 i,则 dp[i][c] = dp[i][c-wgt[i]] + val[i],表示在当前背包容量减去物品 i 的重量后的最大价值基础上加上物品 i 的价值。由于物品可以被无限次选取,我们仍然在考虑物品 i
  3. 初始化:dp[0][...] = 0,表示当没有物品可选时,任何容量的背包的最大价值都是0。

  4. 目标:dp[n][cap],表示考虑所有 n 个物品,当背包容量为 cap 时能达到的最大价值。

 

那为什么转移方程不是 dp[i][c] = max(dp[i-1][c], max(dp[i-1][c-wgt[i-1]] + val[i-1],dp[i][c-wgt[i-1]] + val[i-1]))

 

GPT-4-Turbo

您提出的状态转移方程: [dp[i][c] = max(dp[i-1][c], max(dp[i-1][c-wgt[i-1]] + val[i-1], dp[i][c-wgt[i-1]] + val[i-1]))]

实际上包含了冗余的比较。这是因为,当我们在解决完全背包问题时,对于每个物品,我们有两个选择:不选这个物品,或者选这个物品。如果选择不选这个物品,我们就直接继承了前一个状态的值,即 dp[i-1][c]。如果选择选这个物品,我们需要考虑的是在当前物品可以被无限选取的情况下,选择这个物品后的最优解,即 dp[i][c-wgt[i-1]] + val[i-1]

在这里,dp[i][c-wgt[i-1]] + val[i-1] 已经隐含了 dp[i-1][c-wgt[i-1]] + val[i-1] 的情况。这是因为 dp[i][c-wgt[i-1]] 已经考虑了所有包括第 i 个物品在内的选择,这自然包括了从不选择第 i 个物品到选择多次第 i 个物品的所有情况。因此,dp[i][c-wgt[i-1]] + val[i-1] 实际上已经覆盖了 dp[i-1][c-wgt[i-1]] + val[i-1] 的情况,使得后者成为前者的一个子情况。

因此,原始的状态转移方程: [dp[i][c] = \max(dp[i-1][c], dp[i][c-wgt[i-1]] + val[i-1])]

已经足够覆盖所有情况,无需再进行冗余的比较。这个方程简洁地表达了完全背包问题的核心思想:对于每个物品,我们可以选择不选它,或者在选它的情况下,考虑包括它自身在内的所有可能性。

 

三、GPT-4-Turbod的java实现

 1 public class CompleteKnapsack {
 2 
 3     /**
 4      * 解决完全背包问题的函数
 5      * @param wgt 物品重量数组
 6      * @param val 物品价值数组
 7      * @param cap 背包容量
 8      * @return 背包能装入物品的最大价值
 9      */
10     public static int completeKnapsack(int[] wgt, int[] val, int cap) {
11         int n = wgt.length; // 物品的数量
12         int[][] dp = new int[n + 1][cap + 1]; // dp数组,多出的一行一列是为了方便处理边界情况
13 
14         // 初始化dp数组,Java默认初始化为0,所以这里可以省略
15 
16         // 遍历所有物品
17         for (int i = 1; i <= n; i++) {
18             // 遍历所有可能的背包容量
19             for (int c = 0; c <= cap; c++) {
20                 // 不选当前物品i
21                 dp[i][c] = dp[i - 1][c];
22                 // 选当前物品i,前提是背包容量足够
23                 if (c >= wgt[i - 1]) {
24                     dp[i][c] = Math.max(dp[i][c], dp[i][c - wgt[i - 1]] + val[i - 1]);
25                 }
26             }
27         }
28 
29         // 返回考虑所有物品,背包容量为cap时的最大价值
30         return dp[n][cap];
31     }
32 
33     public static void main(String[] args) {
34         int[] wgt = {1, 3, 4}; // 物品重量
35         int[] val = {15, 20, 30}; // 物品价值
36         int cap = 4; // 背包容量
37 
38         System.out.println("最大价值: " + completeKnapsack(wgt, val, cap));
39     }
40 }
View Code

 

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

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

相关文章

MySQL5.7安装详细过程--window系统

一:MySQL5.7安装详细过程--window系统1.1、下载MySQL5.7安装包https://downloads.mysql.com/archives/community/1.2、将文件解压到盘符中你可以解压到你想解压的位置,放在C或其他盘符都可以。1.3、配置MySQL的环境变量由于我们下载的不是exe或者msi版本,不能直接双击安装,…

一文学会 Kubernetes Pod 的生命周期管理(转载)

收获 了解 Pod 的状态(Status) 了解 pod 阶段(Phase) 了解 Pod conditions了解容器状态(Status) 保持容器健康了解容器自动重启使用探活(liveness)探针(Probe)检查容器的健康状况如果程序启动缓慢,请使用 startup probeLiveness probe 一些建议 在容器启动和关闭时执…

Django国际化与本地化指南

title: Django国际化与本地化指南 date: 2024/5/12 16:51:04 updated: 2024/5/12 16:51:04 categories:后端开发tags:Django-i18n 本地化-L10n 多语言 国际化 翻译工具 表单验证 性能优化引言 在数字化时代,网站和应用程序必须跨越地域限制,服务于全球用户。这就是国际化(In…

二分图(例题)

https://www.cnblogs.com/kuangbiaopilihu/p/18184536$\quad $ 这里不再介绍二分图的基础知识,只是一些例题的解释。$\quad $ 当然,这道题可以用二分+并查集来解决。但这是二分图专辑,所以介绍一下二分图做法。 $\quad $ 首先如果两个罪犯之间有仇恨,那么当他们不在同一所…

记一次阿里云服务器被ssh爆破

查看Ubuntu登录日志: cat /var/log/auth.log 发现我的服务器被ssh爆破针对这一现象 我决定构造一个脚本 来防范这种爆破式攻击 具体思路就是通过脚本判定特定IP的登录失败次数 如果多于两次 关闭进程 并且ban IP 首先就是将登录失败的ip单独拎出来 cat /var/log/auth.log.1 | …

海康威视

1 static关键字作用 修饰局部变量 ​ static修饰局部变量时,使得被修饰的变量成为静态变量,存储在静态区。存储在静态区的数据生命周期与程序相同,在main函数之前初始化,在程序退出时销毁。(无论是局部静态还是全局静态) 修饰全局变量 ​ 全局变量本来就存储在静态区,因…

.net core 实现注册同一服务类型的多个服务实例

1. 注册服务。给 IMyDependency 注册两个不同的实现。builder.Services.AddSingleton<IMyDependency, MyDependency>(); builder.Services.AddSingleton<IMyDependency, DifferentDependency>();2. 依赖注入。通过 IEnumerable<IMyDependency> 获取两个不同的…

PWN的一些前置知识

PWN的一些前置知识点 虽然我超想打web方向,但是其实感觉每个方向都一窍不通555,算了先学学pwn和misc再说吧 大致流程 查看文件 使用checksec命令,查看是否开启PIE,ASLR等,查看是否有canary(栈保护的机制) 静态分析 使用IDA pro或者其他静态分析软件,获取软件逆向代码 动…