首页 > 其他分享 >动态规划 01背包问题 二维转一维过程及理解

动态规划 01背包问题 二维转一维过程及理解

时间:2023-07-06 19:12:26浏览次数:32  
标签:01 weight int 更新 二维 一维 dp

 

1.  01背包:二维朴素写法

 

public static int getMaxValue(int[] weight, int[] values, int w) {

int n = weight.length;
int[][] dp = new int[n + 1][w + 1];

for (int i = 1; i <= n; i++) {
for (int j = 1; j <= w; j++) {
if (j >= weight[i - 1]) {
dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - weight[i - 1]] + values[i - 1]);
}
}
}

return dp[n][w];
}

2.  01背包:二维朴素写法 —> 一维空间优化写法

 

public static int getMaxValue2(int[] weight, int[] values, int w) {
int n = weight.length;

int[] dp = new int[w + 1];
for (int i = 1; i <= n; i++) {
for (int j = w; j >= weight[i-1]; j--) {
if (j >= weight[i - 1]) {
dp[j] = Math.max(dp[j], dp[j - weight[i - 1]] + values[i - 1]);
}
}
}

return dp[w];
}

3.  以上二维转一维 两个重点问题

3.1  为何可以用一维数组代替二维数组?

二维数组更新方式为

f[i][j] = f[i - 1][j] # 不含i的所有选法的最大价值
if j >= v[i]: # 判断含i的选法是否成立
f[i][j] = max(f[i][j], f[i - 1][j - v[i]] + w[i])


可以看出f[i][:]只依赖于f[i-1][:],所以根本没必要保留之前的f[i-2][:]等状态值;

使得空间从o(n*m)缩小到o(m),n,m分别为物品个数和背包体积
其实每个物品的体积和价值在该层循环结束后也不会再用上,这里也可以压缩为两个o(1)的空间

 

3.2 、为何要逆序更新?


一维数组更新方式为

while j >= v[i]:
dp[j] = max(dp[j], dp[j - v[i]] + w[i])


我们只有上一层dp值的一维数组,更新dp值只能原地滚动更改;


注意到,

当我们更新索引值较大的dp值时,需要用到索引值较小的上一层dp值dp[j - v[i]];
也就是说,在更新索引值较大的dp值之前,索引值较小的上一层dp值必须还在,还没被更新;
所以只能索引从大到小更新。

 

看这段话是不是理解起来比较难,那我们 模拟一遍  逆序的过程  一切疑问皆明了

 

标签:01,weight,int,更新,二维,一维,dp
From: https://www.cnblogs.com/shoshana-kong/p/17533085.html

相关文章

  • vba 二维码生成
    PrivateDeclarePtrSafeFunctionOpenProcessLib"kernel32"(ByValdwDesiredAccessAsLong,ByValbInheritHandleAsLong,ByValdwProcessIdAsLong)AsLongPrivateDeclarePtrSafeFunctionWaitForSingleObjectLib"kernel32"(ByValhHa......
  • 一维数组
    一维数组一维数组定义&形式是一组数据类型相同的变量,可以存放一组数据数组名[下标]❗数组地址数组在内存中的地址是连续的C++将数组名解释为数组首个元素的地址⚠数组名为常量,不能更改,例如int类型数组a使用a++❎指针值可以改变,int*p=a使用p++✅数组第0个元......
  • 01.net6集成redis
    安装redis自己使用dockercompose安装redis,yml文件如下:version:'3.9'services:redis:image:redis:6.2.5container_name:docker_redisprivileged:truevolumes:-./data:/data-./conf/redis.conf:/usr/local/etc/redis/redis.conf......
  • 错误:rpmdb: BDB0113 Thread/process 8709/139671674841152 failed
    rpm库报错错误:rpmdb:BDB0113Thread/process8709/139671674841152failed:BDB1507ThreaddiedinBerkeleyDBlibrary错误:db5错误(-30973)来自dbenv->failchk:BDB0087DB_RUNRECOVERY:Fatalerror,rundatabaserecovery错误:无法使用db5- (-30973)打开Packages......
  • 使用Stable Diffusion生成艺术二维码
    在数字艺术的世界中,二维码已经从单纯的信息承载工具转变为可以展示艺术表达的媒介。这是通过使用StableDiffusion的技术实现的,它可以将任何二维码转化为独特的艺术作品。接下来,我们将一步步教你如何使用StableDiffusion生成艺术二维码。需要的工具你需要一款名为AUTOMATIC1111......
  • 云拨测全面升级丨单次拨测低至 0.001 元
    作者:少焉随着云原生、微服务技术的发展,可观测需求变得越来越强烈,作为可观测技术的重要能力之一,云拨测(SyntheticsMonitor)由于其零侵入、开箱即用、主动式监测手段,也受到很多用户的青睐,很多通过云拨测主动监测自身服务的可用性,先于用户发现线上异常;也会通过云拨测分析和优化网页加......
  • gym101573I Favorite Points
    gym101573IFavoritePoints纪念一下。#include<bits/stdc++.h>#defineLLlonglong#definePLLpair<LL,LL>#defineMPmake_pair#defineEBemplace_back#defineall(x)x.begin(),x.end()usingnamespacestd;template<typenameT>voidchkmn(T......
  • JAVA_DAY_01
    第一天1.jdk针对Java开发员的软件开发工具包。1.5:{自动拆箱和装箱、foreach循环、可变参数}​1.8:{1、Lamdba表达式2、函数式接口3、方法引用和构造引用4、StreamAPI}​java的运行机制,编写定义为.java格式的源代码。​通过javac命令格式调用编译器(JDK)对源代码进行编......
  • vue生成二维码图片并且下载图片到本地
    一、安装生成二维码插件qrcode.jsnpminstall--saveqrcodejs2二、封装组件<template><div><divid="qrcode"></div></div></template><script>//二维码importQRCodefrom'qrcodejs2'......
  • GDAL源码剖析与开发指南 - 李民录 - 2014
    本书适合地理信息系统和遥感等相关专业应用的开发人员阅读参考。本书中大部分的示例代码都是使用C/C++语言编写,有一定C/C++语言基础的读者能够快速上手开发相关应用。目录第1章GDAL简介.................1第2章OGR空间参考.............42第3章OGR库说明........................