力扣- 背包问题

关于背包问题,推荐卡哥的视频,结合代码随想录食用,效果绝佳!!!

传送门:

带你学透0-1背包问题!| 关于背包问题,你不清楚的地方,这里都讲了!| 动态规划经典问题 | 数据结构与算法_哔哩哔哩_bilibili

带你学透01背包问题(滚动数组篇) | 从此对背包问题不再迷茫!_哔哩哔哩_bilibili

带你学透完全背包问题! 和 01背包有什么差别?遍历顺序上有什么讲究?_哔哩哔哩_bilibili

好了,开始今天正文:  

这是一篇纯分享总结内容的文章,想get背包问题的⬆  强推卡哥的讲解视频

什么是背包问题?

我们一般使用weights[],values[]数组来存贮每个物品的重量和价值

01 背包

有n件物品和一个最多能背重量为w 的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。每件物品只能用一次,求解将哪些物品装入背包里物品价值总和最大。

对于01 背包问题

二维dp

dp数组的含义:

dp[i][j] 表示0 - i物品任取放入背包容量为j的背包中的最大价值

递推公式:

dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - W[j] + V[i])

dp[i-1][j-w[i]]表示选了当前第i个物品后只能从前i-1个物品中进行选择,并且扣除了当前第i个物品的weight;

而dp[i][j]的推导由取i 和 不取i物品获得的最大价值 取较大值进行推导的

初始化:

for(int j = 1; j <= n; j++) {            
    if(j >= weights[0]) {                
        dp[0][j] = values[0];            
    }        
}

二维dp代码:

import java.util.*;
 
public class Main {
    public static void main (String[] args) {
        Scanner sc = new Scanner(System.in);
        int m = sc.nextInt();
        int n = sc.nextInt();
         
        int[] values = new int[m];
        int[] weights = new int[m];
        for(int i = 0; i < m; i++) {
            weights[i] = sc.nextInt();
        }
        for(int i = 0; i < m; i++) {
            values[i] = sc.nextInt();
        }
         
        // dp[i][j] 表示0-i物品任取放入容量为j的背包中产生的最大价值
        int[][] dp = new int[m][n + 1];
        // 初始化
        for(int j = 1; j <= n; j++) {
            if(j >= weights[0]) {
                dp[0][j] = values[0];
            }
        }
         
        for(int i = 1; i < m; i++) {    // 先物品
            for(int j = 0; j <= n; j++) {   // 后背包容量
                if (j < weights[i]) {
                    dp[i][j] = dp[i - 1][j];
                } else {
                    dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - weights[i]] + values[i]);
                }
            }
        }
        System.out.println(dp[m - 1][n]);
    }
}

一维dp(滚动数组)

对于背包问题其实状态都是可以压缩的。

在使用二维数组的时候,递推公式:dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);

其实可以发现如果把dp[i - 1]那一层拷贝到dp[i]上,表达式完全可以是:dp[i][j] = max(dp[i][j], dp[i][j - weight[i]] + value[i]);

与其把dp[i - 1]这一层拷贝到dp[i]上,不如只用一个一维数组了,只用dp[j](一维数组,也可以理解是一个滚动数组)。

这就是滚动数组的由来,需要满足的条件是上一层可以重复利用,直接拷贝到当前层。

dp数组的含义:

dp[i][j] 表示背包容量为j的背包中的最大价值

递推公式:

dp[j] = max(dp[j],dp[j - W[i]] + V[i]);

这里因为是滚动数组,每次都是滚动升级,需要依靠前面的状态

需要注意的是,在遍历背包的时候需要倒序遍历确保所有物品最多只取一次

一维dp代码:

import java.util.*;
 
public class Main {
    public static void main (String[] args) {
        // 滚动数组
        Scanner sc = new Scanner(System.in);
        int m = sc.nextInt();
        int n = sc.nextInt();
         
        int[] values = new int[m];
        int[] weights = new int[m];
        for(int i = 0; i < m; i++) {
            weights[i] = sc.nextInt();
        }
        for(int i = 0; i < m; i++) {
            values[i] = sc.nextInt();
        }
         
        // dp[j] 表示放入容量为j的背包中产生的最大价值
        int[] dp = new int[n + 1];
        // 初始化
        dp[0] = 0;
         
        for(int i = 0; i < m; i++) {    // 先物品
            for(int j = n; j >= 0; j--) {   // 后背包容量
                if(j >= weights[i]) {
                    dp[j] = Math.max(dp[j],dp[j - weights[i]] + values[i]);
                }
            }
        }
        System.out.println(dp[n]);
    }
}

完全背包

有N件物品和一个最多能背重量为W的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。每件物品都有无限个(也就是可以放入背包多次),求解将哪些物品装入背包里物品价值总和最大。

完全背包和01背包问题唯一不同的地方就是,每种物品有无限件

二维dp

dp数组的含义:

dp[i][j] 表示0 - i物品任取放入背包容量为j的背包中的最大价值

递推公式:

dp[i][j] = max(dp[i - 1][j], dp[i][j - W[j] + V[i])

dp[i][j-w[i]]表示尽管我选了当前物品,也把当前物品的weight从背包容量中扣除了,但是我仍然可以在这i个物品中继续选择。

与01背包问题其区别在于每个物品是否可重复选。

二维dp代码:

import java.util.*;
 
public class Main {
    public static void main (String[] args) {
        Scanner sc = new Scanner(System.in);
         
        int n = sc.nextInt();
        int v = sc.nextInt();
         
        int[] weights = new int[n];
        int[] values = new int[n];
        for(int i = 0; i < n; i++) {
            weights[i] = sc.nextInt();
            values[i] = sc.nextInt();
        }
         
        int[][] dp = new int[n][v + 1];
        for(int j = 0; j <= v; j++) {
            if(j == 0) {
                dp[0][j] = 0;
            } else {
                int k = j / weights[0];
                dp[0][j] = k * values[0];
            }
        }
         
        for(int i = 1; i < n; i++) {
            for(int j = 0; j <= v; j++) {
                if(j < weights[i]) {
                    dp[i][j] = dp[i - 1][j];
                } else {
                    dp[i][j] = Math.max(dp[i - 1][j],dp[i][j - weights[i]] + values[i]);
                }
            }
        }
         
        System.out.println(dp[n - 1][v]);
    }
}

一维dp

与01背包问题代码区别就是在遍历背包数量的时候使用正序遍历

其中原由: 代码随想录 (programmercarl.com)

一维dp代码:

import java.util.*;
 
public class Main {
    public static void main (String[] args) {
        Scanner sc = new Scanner(System.in);
         
        int n = sc.nextInt();
        int v = sc.nextInt();
         
        int[] weights = new int[n];
        int[] values = new int[n];
        for(int i = 0; i < n; i++) {
            weights[i] = sc.nextInt();
            values[i] = sc.nextInt();
        }
         
        int[] dp = new int[v + 1];
         
        for(int i = 0; i < n; i++) {
            for(int j = weights[i]; j <= v; j++) {
                dp[j] = Math.max(dp[j],dp[j - weights[i]] + values[i]);
            }
        }
        System.out.println(dp[v]);
    }
}

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

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

相关文章

HyperWorks汽车B-柱网格变形

在这一节&#xff0c;将练习如何使用变形域&#xff0c;实现汽车 B-柱有限元模型的网格变形。 图 7-13 网格变形前后的 B 柱模型 Step01&#xff1a;读取并查看模型。 打开模型文件 Exercise_7c.hm。 Step02&#xff1a;创建变形域。 (1) 通过路径 HyperMorph > Morph…

C++笔记之原子操作

C++笔记之原子操作 code review! 文章目录 C++笔记之原子操作1.初始化2.赋值3.取值4.赋给另一个原子类型5.`exchange`6.`compare_exchange_weak` 和 `compare_exchange_strong`使用场景7.注意事项在 C++ 中,原子类型提供了对共享变量的无锁操作,确保多线程环境下的安全。以下…

【Linux】为什么创建目录文件,硬链接数是2;创建普通文件时,硬链接数是1?(超详细图文解答)

前言 大家好吖&#xff0c;欢迎来到 YY 滴Linux系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过C的老铁 主要内容含&#xff1a; 欢迎订阅 YY滴C专栏&#xff01;更多干货持续更新&#xff01;以下是传送门&#xff01; YY的《C》专栏YY的《C11》专栏YY的《Lin…

图示详解OpenEuler下Samba多用户身份验证配置、测试

前言 前文《图例详解OpenEuler下Samba安装、配置和测试》已对Samba服务的工作原理、安装、配置和测试&#xff0c;做了系统的介绍&#xff0c;并对匿名用户的访问samba服务器做了配置&#xff0c;相必读者已对samba服务的流程有了初步、系统的了解&#xff0c;本文在以上基础上…

DevExpress WinForms中文教程:Data Grid - 如何完成数据输入验证?

本教程介绍DevExpress WinForm的Data Grid控件是如何利用网格组件完成数据输入验证的。 P.S&#xff1a;DevExpress WinForms拥有180组件和UI库&#xff0c;能为Windows Forms平台创建具有影响力的业务解决方案。DevExpress WinForms能完美构建流畅、美观且易于使用的应用程序…

vim 操作

vim编辑器的有三种工作模式&#xff1a;命令模式、插入模式和底行命令模式 打开进入命令模式&#xff1a; 由命令模式到输入模式&#xff1a;i:在光标前插&#xff1b;a:在光标后插&#xff1b;o:在下一行插 由输入模式进入命令模式&#xff1a;esc 由命令模式进入底行命令…

LabVIEW技术难度最大的程序

在LabVIEW开发中&#xff0c;技术难度最大的程序通常涉及复杂的系统架构、高精度的控制要求、大量数据处理&#xff0c;以及跨平台或多硬件设备的集成。以下是几类具有高技术难度的LabVIEW程序&#xff1a; 1. 高精度实时控制系统 LabVIEW中涉及高精度实时控制的系统程序&…

探索极致性能:R9-9950X与I9-14900K的深度较量

处理器是电脑及服务器的心脏&#xff0c;处理器的性能直接影响着电脑或服务器的运行效率、多任务处理能力以及整体用户体验。一款优秀的处理器&#xff0c;能够确保系统流畅运行&#xff0c;无论是处理复杂的数据分析、高强度的图形渲染&#xff0c;还是享受沉浸式的游戏体验&a…

【spring ai】java 实现RAG检索增强,超快速入门

rag 需求产生的背景介绍&#xff1a; 在使用大模型时&#xff0c;一个常见的问题是模型会产生幻觉&#xff08;即生成的内容与事实不符&#xff09;&#xff0c;同时由于缺乏企业内部数据的支持&#xff0c;导致其回答往往不够精准和具体&#xff0c;偏向于泛泛而谈。这些问题…

Selenium实现滑动滑块验证码验证!

背景&#xff1a;在部分的登录中有滑动验证码的验证&#xff0c;由于滑动验证码的缺块是随机的就导致实现起来比较困难&#xff01; 01、实现方案 模板匹配 通过openCV分析两个图片的相似度&#xff0c;获取两个相似度很高图片的坐标&#xff0c;从而计算两个图片的距离。 轮…

基础sql

在执行删除操作之前&#xff0c;建议先运行一个 SELECT 查询来确认你要删除的记录。这可以帮助你避免误删数据。 删除字段id默认值为空字符串的所有数据 delete from users where id ; 删除字段id默认值为null的所有数据 delete from users where id is null; 删除字段upd…

数据容器(序列)的切片

1.数据容器&#xff1a;列表&#xff0c;元组&#xff0c;字符串 2..切片可以提取序列中的片段或整个序列 ##切片的格式为&#xff1a;变量名[ 起始位置:停止位置&#xff1a;步数] #起始位置为序列首位时可省略不写&#xff0c;停止位置为序列尾部时也如此&#xff0c;##停止…

多jdk版本环境下,jenkins系统设置需指定JAVA_HOME环境变量

一、背景 由于不同项目对jdk版本的要求不同&#xff0c;有些是要求jdk11&#xff0c;有些只需要jdk8即可。 而linux机器上安装jdk的方式又多种多样&#xff0c;最后导致jenkins打包到底使用的是哪个jdk&#xff0c;比较混乱。 1、java在哪 > whereis java java: /usr/bin/…

sql实战解析-sum()over(partition by xx order by xx)

该窗口函数功能 sum( c )over( partition by a order by b) 按照一定规则汇总c的值&#xff0c;具体规则为以a分组&#xff0c;每组内按照b进行排序&#xff0c;汇总第一行至当前行的c的加和值。 从简单开始一步一步讲&#xff0c; 1、sum( )over( ) 对所有行进行求和 2、sum(…

第二十五:IP网络层的数据,IP数据报

在数据链路层传输的数据叫帧&#xff0c;帧是数据链路层的传输单元。 那么在IP网络层的数据也有一个叫法IP数据报。 IP数据报 IP数据报首部 数据。 数据是传输层传递过来的报文&#xff1b;IP数据报首部格式如下&#xff1a; IP 报头的最小长度为 20 字节&#xff0c;上图…

打造爆款店铺:eBay、Temu、亚马逊卖家如何借助测评提升流量转销量?

无论是eBay还是在亚马逊、沃尔玛、Temu、速卖通、敦煌网、shopee、lazada平台上&#xff0c;流量是店铺获得曝光和销售的关键因素之一。提高店铺流量意味着能够吸引更多的买家浏览和关注&#xff0c;从而增加销售机会。那么&#xff0c;在eBay、Temu、亚马逊店铺中如何有效地提…

大模型还能让我们望梅止渴多久?

大模型梦碎的时间点似乎越来越近。过去一周&#xff0c;有关人工智能的消息糟糕多于积极。 周初&#xff0c;诺贝尔物理学奖和化学奖接连砸向时下正热的人工智能领域。这些奖项出人意料且鼓舞人心&#xff0c;意味着人工智能的确已经根本性地改变了我们生活和科学体系的方方面…

这是我见过最全LLM大模型基础知识学习汇总,建议收藏!

关于如何入门LLM&#xff0c;大多数回答都提到了调用API、训练微调和应用。但是大模型更新迭代太快&#xff0c;这个月发布的大模型打榜成功&#xff0c;仅仅过了一个月就被其他模型超越。训练微调也已经不是难事&#xff0c;有大量开源的微调框架&#xff08;llamafactory、fi…

大模型本地部署教程 | 搭建本地AI问答系统

前言 大家好&#xff0c;因为对AI大模型很感兴趣&#xff0c;相信很多兄弟们跟我一样&#xff0c;所以最近花时间了解了一些&#xff0c;有一些总结&#xff0c;分享给大家&#xff0c;希望对各位有所帮助。 本文将讲解如何在本地搭建一个简易的AI问答系统&#xff0c;主要用j…

【网络】【Linux】多路转接技术

多路转接技术 文章目录 1.select1.1select系统调用及参数介绍1.2select基本工作流程1.3select技术实现echo服务器1.4select优缺点1.5select的适用场景 2.poll&#xff08;了解&#xff09;2.1poll系统调用及参数介绍2.2poll技术实现echo服务器2.3poll优缺点 3.epoll3.1epoll系…