动态规划DP--背包问题

news2024/12/26 1:00:42

文章目录

  • 0-1背包问题 -- 问题定义
    • 动态规划解法
    • 代码
    • 题目:分割等和子集
    • 题解

0-1背包问题 – 问题定义

在 0-1 背包问题中,给定一个背包的最大容量 W,以及 n 个物品,每个物品有两个属性:

  • 重量:第 i 个物品的重量为 wt[i]
  • 价值:第 i 个物品的价值为 val[i]

目标是选择若干个物品装入背包,使得在不超过背包最大容量 W 的前提下,装入背包的物品的总价值最大

注意:0-1 背包中的 “0-1” 指的是每个物品只能被选取一次(即要么选择该物品,要么不选,不存在把物品拆一半放入背包)。

这个0-1背包问题很经典。详情可以买本labuladong的算法笔记这本书看看,或者去网站看。

动态规划解法

背包问题无非就是状态 + 选择,状态转移方程比较特殊。

第一步:明确状态+选择
状态:只要给几个物品一个背包的容量限制,就形成了一个背包问题呀。所以状态有两个,就是背包的容量可选择的物品

选择:装进背包 or 不装进背包

框架:

for 状态1 in 状态1的所有取值:
    for 状态2 in 状态2的所有取值:
        for ...
            dp[状态1][状态2][...] = 择优(选择1,选择2...)

第二步:要明确 dp 数组的定义

  1. dp[i][w] 的定义

    • dp[i][w] 表示在考虑前 i 个物品时,当前背包容量为 w 的情况下可以获得的最大价值。
    • 注意:i 是从 1 开始计数的,意味着 i 对应的是第 i-1 个物品。
  2. 两种情况的状态转移

    • 如果不选第 i 个物品

      • 那么当前背包的最大价值等于不考虑第 i 个物品时的最大价值,即 dp[i][w] = dp[i-1][w]。这个值继承了前 i-1 个物品在背包容量为 w 时的最大价值。
    • 如果选第 i 个物品

      • 你可以将第 i 个物品装入背包,前提是当前背包的容量 w 要大于等于该物品的重量 wt[i-1]
      • 在这种情况下,当前物品的总价值应该等于第 i-1 个物品在容量为 w - wt[i-1] 时的最大价值,再加上该物品的价值 val[i-1]
      • 公式为:dp[i][w] = val[i-1] + dp[i-1][w - wt[i-1]]
// ①定义状态
int[][] dp[N+1][W+1]
// ②初始化状态 因为没有物品或者背包没有空间的时候,能装的最大价值就是 0
dp[0][..] = 0
dp[..][0] = 0
// ③状态转移方程
for i in [1..N]:
    for w in [1..W]:
        dp[i][w] = max(
            把物品 i 装进背包,
            不把物品 i 装进背包
        )
return dp[N][W]

代码

int knapsack(int W, int N, int[] wt, int[] val) {
    int N == wt.length;
    // 定义状态 dp[i][w] 表示: 对于前 i 个物品(从 1 开始计数),当前背包的容量为 w 时,这种情况下可以装下的最大价值是 dp[i][w]
    int[][] dp = new int[N + 1][W + 1];
    for (int i = 1; i <= N; i++) {
        for (int w = 1; w <= W; w++) {
            if (w - wt[i - 1] < 0) {
                // 这种情况下只能选择不装入背包
                dp[i][w] = dp[i - 1][w];
            } else {
                // 装入或者不装入背包,择优
                dp[i][w] = Math.max(
                    dp[i - 1][w - wt[i-1]] + val[i-1], 
                    dp[i - 1][w]
                );
            }
        }
    }
    
    return dp[N][W];
}

题目:分割等和子集

原题链接: 分割等和子集
在这里插入图片描述

题解

方法1:

  • dp[i][j] = dp[i-1][j] || dp[i-1][j-nums[i-1]]:只要有一种情况成立,dp[i][j] 就为 true。即:
    • 要么不选第 i 个数(dp[i-1][j]true),则前 i-1 个数已经能够组成和为 j
    • 要么选择第 i 个数(dp[i-1][j-nums[i-1]]true),则前 i-1 个数能组成和为 j - nums[i-1],加上 nums[i-1] 就可以使总和为 j
 public boolean canPartition(int[] nums) {
     int sum = 0;
     for (int num : nums) sum += num;
     // 和为奇数时,不可能划分成两个和相等的集合
     if (sum % 2 != 0) return false;
     int target = sum / 2;
     // ①定义状态  dp[i][j] 表示前i个数中能否选出若干个  使得和为 j(j为背包容量)  则为true  否则false
     boolean[][] dp = new boolean[nums.length + 1][target + 1];
     // ②初始化状态
     for (int i = 0; i <= nums.length; i++)
         dp[i][0] = true; // 背包容量为 0 时  不选任何物品就满足

     // ③状态转移
     for (int i = 1; i <= nums.length; i++) {
         for (int j = 1; j <= target; j++) {
             if (j - nums[i - 1] < 0) {
                 // 背包容量不足,不能装入第 i 个物品
                 dp[i][j] = dp[i - 1][j];
             } else {
                 // 装入或不装入背包
                 dp[i][j] = dp[i - 1][j] || dp[i - 1][j - nums[i - 1]];
             }
         }
     }
     return dp[nums.length][target];
 }

这段代码是一个典型的0-1 背包问题的解法,问题是:能否从数组 nums 中找到若干个数,使它们的和等于 target(即总和的一半)。其中 dp[i][j] 表示前 i 个数能否选出若干个数,使它们的和恰好为 j。现在解释这一行代码:

dp[i][j] = dp[i - 1][j] || dp[i - 1][j - nums[i - 1]];

方法2:
在每次状态转移时,dp[i][j] 只依赖于上一行的状态 dp[i-1][j] 和 dp[i-1][j - nums[i-1]],所以可以将其优化为一维数组 dp[j],从而减少空间复杂度。

在遍历数组时,我们从后向前更新 dp 数组。这样做可以避免同一轮中重复使用同一个元素,即确保每个元素只能使用一次。

public boolean canPartition(int[] nums) {
    // 计算数组总和
    int sum = 0;
    for (int num : nums) {
        sum += num;
    }
    // 如果总和为奇数,无法分成两个子集
    if (sum % 2 != 0) return false;
    // 目标和是总和的一半
    int target = sum / 2;

    // ①定义状态  dp[i] 表示是否可以选出若干个元素,使得和为 i
    boolean[] dp = new boolean[target + 1];

    // ②初始化状态
    dp[0] = true;

    // ③状态转移
    for (int i = 0; i < nums.length; i++) {
        for (int j = target; j >= 0; j--) {
            if (j - nums[i] >= 0) {
                dp[j] = dp[j] | dp[j - nums[i]];
            }
        }
    }
    return dp[target];
}


❤觉得有用的可以留个关注~~~❤

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

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

相关文章

[数据集][目标检测]电动车入梯进电梯电单车入梯检测数据集VOC+YOLO格式7106张3类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;7106 标注数量(xml文件个数)&#xff1a;7106 标注数量(txt文件个数)&#xff1a;7106 标注…

广义回归神经网络(GRNN)

一、简介 广义回归神经网络 (General Regression Neural Network &#xff0c; GRNN) 的概念是由德 国科学家多纳德提出的&#xff0c;是径向基网络的其中一种 。因为其是以数理统计为基 础的&#xff0c;因此 GRNN 可以依据样本数据逼近其中包含的非线性映射关系。即使样本 数…

家里有猫用宠物空气净化器有用吗?希喂、米家、有哈哪款更好

在快节奏的现代生活中&#xff0c;越来越多的人选择宠物作为心灵的慰藉与生活的伴侣。起初&#xff0c;这份陪伴的需求简单而纯粹&#xff0c;但随着日子一天天过去&#xff0c;那份简单的情感逐渐生根发芽&#xff0c;成长为深厚的责任与爱。我在前两年养了两只猫&#xff0c;…

一款云笔记支持在线协同文档,脑图,白板演示的工具,多个设备同步,让灵感与你同行(附源码)

前言 在快节奏的工作环境中&#xff0c;如何高-效地记录、整理并分享工作笔记已经成为了一项重要的技能。传统的笔记方式往往难以满足跨设备、即时同步以及团队协作的需求&#xff0c;导致信息孤岛和工作效率低下。面对这样的挑战&#xff0c;我们迫切需要一种全新的工具来改变…

【ArcGIS Pro原理第一期】各种空间插值原理:GPI、LPI、IDW等

ArcGIS Pro原理第一期&#xff1a;空间插值原理 空间插值方法概述1.1 全局多项式&#xff08;global polynomial interpolation, GPI&#xff09;方法原理使用范围 1.2 局部多项式&#xff08;local polynomial interpolation, LPI&#xff09;方法原理精度测量&#xff08;Mea…

echarts进度

echarts图表集 let numdata["I级",II级,III级,IV级,V级,劣V级] let pricedata40 option {backgroundColor: #0f375f,title: {show: false,text: ,left: center,top: 30%,textStyle: {color: #00D5FF,fontSize: 16,},},tooltip: {show: false},grid: {// show: true,…

鸿蒙界面开发——组件(5):菜单Menu 绑定菜单

菜单组件Menu Menu组件需和bindMenu或bindContextMenu方法配合使用&#xff0c;不支持作为普通组件单独使用。 Menu 以垂直列表形式显示的菜单。包含MenuItem、MenuItemGroup子组件。 Menu()作为菜单的固定容器&#xff0c;无参数。 MenuItem(value?: MenuItemOptions| Cust…

DC-DC开关稳压电路

前面所讲的线性稳压电路具有结构简单、调节方便、输出电压稳定性强、纹波电压小等优点。但是&#xff0c;由于调整管始终工作在放大状态&#xff0c;自身功耗较大&#xff0c;故效率较低&#xff0c;甚至仅为30%~40%。而且&#xff0c;为了解决调整管散热问题&#xff0c;必须安…

Linux-(系统启动、用户管理)

目录 前言 关机&重启命令 基本介绍 注意细节 用户登录和注销 注意&#xff1a; 用户管理 基本介绍 添加用户 指定/修改密码 删除用户 查询用户信息 切换用户 查看当前用户登录用户 用户组 新增组 删除组 查看所有组 修改用户所属组 创建用户时指定用户…

如何在车载中控上进行UI自动化测试

说到车载测试&#xff0c;很多人都很好奇&#xff0c;车载中控是否需要UI自动化测试&#xff0c;从市场反馈来说&#xff0c;在6-7年之前的车载中控测试就已经介入UI自动化测试&#xff0c;那时候还是使用javaUIautomator框架。现在大部分都已经更新为PythonAppium框架进行自动…

Fiddler安卓设备抓包基础

Fiddler安卓设备抓包基础 一、下载二、Fiddler设置三、安卓设备设置四、Fiddler工具页面介绍 一、下载 工具名称&#xff1a;Fiddler 下载地址&#xff1a;官网 二、Fiddler设置 1.打开Fiddler 2.打开Tools > Options > Connections进行如下设置&#xff0c;Fiddler…

【C++ Primer Plus习题】10.7

问题: 解答: main.cpp #include <iostream> #include "plorg.h" using namespace std;int main() {plorg p("Plorga");p.showCI();p.setCI(10);p.showCI();return 0; }plorg.h #pragma once#define SIZE 19 class plorg { private:char m_fillName…

allegro约束管理器的学习

1&#xff09;差分线neck mode的使用 2&#xff09;走线区域规则和间距区域规是不同的 3&#xff09;创建区域规则的步骤 分为三个步骤 1在spacing中创建一个区域规则&#xff1b; 2在region中把区域规则赋予它&#xff1b; 3在pcb中&#xff0c;创建一个constraint region sha…

中国次生林林龄分布数据(2020年)

次生林年龄的全国分布对于了解中国森林生态系统和碳储量至关重要。该数据集采用了一种数据驱动的方法&#xff0c;用于提高植被变化跟踪器和连续变化检测与分类算法的性能&#xff0c;通过使用变化检测算法和密集的陆地卫星时间序列来确定次生林的建立时间。 该数据集主要以tif…

实践reflex:以Personalized Sales个人销售网站为例

reflex 是一个使用纯Python构建全栈web应用的库&#xff0c;但是需要使用node&#xff0c;所以你懂的。 官网&#xff1a;Reflex Web apps in Pure Python 手册&#xff1a;Introduction Pynecone: Pynecone 是一个全栈 Python 框架&#xff0c;可以使用纯 Python 构建高性…

2024级新生数组字符串专题题解

一、题解&#xff1a; 1.A-[NOIP2005]校门外的树_24级新生数组字符串训练题 (nowcoder.com) 这题常见的解法有两种&#xff1a; 第一种是这道题我们可以直接按照题目意思枚举 #include<bits/stdc.h> #define int long long using namespace std;int road[10010];sig…

HarmonyOS开发实战( Beta5.0)DevEco Device Tool开发环境搭建实践

通常在嵌入式开发中&#xff0c;很多开发者习惯于使用Windows进行代码的编辑&#xff0c;比如使用Windows的Visual Studio Code进行OpenHarmony代码的开发。但当前阶段&#xff0c;大部分的开发板源码还不支持在Windows环境下进行编译&#xff0c;如Hi3516、Hi3518系列开发板。…

Django+Vue3前后端分离学习(五)(前端登录页面搭建)

1、如果需要使用组合式API&#xff0c;需要安装插件&#xff1a; npm install vite-plugin-vue-setup-extend --save-dev 在vite.config.js里配置&#xff1a; 首先导入: import VueSetupExtend from vite-plugin-vue-setup-extend 添加&#xff1a; 2、创建login.vue 然…

C语言刷题日记(附详解)(4)

一、选填部分 第一题: 下面四个选项中&#xff0c;均是不合法的用户标识符的选项是( ) A. A P_0 do B. float la0 _A C. b-a sizeof int D. b_a temp _123 思路提示&#xff1a;题中所问的是"不合法"的"用户标识符"&#xff0c;要记得&#xff0c;C…

4区升3区的“灌水王者”!7个月还未送审被人评为“小牌大耍”?急投学者注意

【SciencePub学术】本期&#xff0c;给大家介绍的是1本计算机类的SCI——《JOURNAL OF SUPERCOMPUTING》。 优点VS缺点 • 期刊投稿难度较小&#xff0c;接受率较高 • 国人投稿友好&#xff0c;且已经稳定检索了28年 • 去年由中科院4区升为3区 • 普遍反映这本期刊审稿周期…