day 42 01背包

news/2024/10/29 0:28:44/

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

二维数组

  1. dp含义:
    dp[ i ][ j ] 表示从下标为 [ 0 - i ]的物品里任意取,放进容量为 j 的背包,价值总和最大是多少。

  2. 递推公式
    在分析第 i 个物品 dp[ i ][ j ] 能否放到背包j里时,有以下三种情况
    (1)w[ i ] > 背包总重量 不放 dp[ i ][ j ] = dp[ i - 1 ][ j ]
    (2)不放 dp[ i ][ j ] = dp[ i - 1 ][ j ]
    (3)放进去 dp[ i ][ j ] = dp[ i - 1 ][ j - w[ i ] ] + v[ i ]
    则 dp[ i ][ j ] = max (dp[ i - 1 ][ j - w[ i ] ] + v[ i ], dp[ i - 1 ][ j ]

  3. 初始化
    如果物品下标从0开始
    for (int j = weight[0]; j <= bagweight; j++) { dp[0][j] = value[0];}
    如果物品下标从1开始 , 直接初始化为0 就行

  4. 顺序 由递推公式可见,当前值取决于自己左上角的值,那么先遍历重量,再遍历物品 和 先遍历物品再遍历重量是一样的

一维滚动数组
原理:当前层的状态只与上一层有关系,所以把上一层的数字拷贝下来,到当前层进行计算,用新的值进行覆盖,把二维数组压缩为一维

  1. dp含义:
    dp[ j ] 容量为j的背包能装的最大价值

  2. 递推公式
    dp[ j ] = max(dp[ j ], dp[ j - w [ i ] ] + v[ i ])
    因为该层数据使上一层拷贝下来的所以原本的 dp[ j ] == dp[ i - 1 ][ j ]

    在分析第 i 个物品 dp[ i ][ j ] 能否放到背包j里时,有以下三种情况
    (1)w[ i ] > 背包总重量 不放 dp[ i ][ j ] = dp[ i - 1 ][ j ]
    (2)不放 dp[ i ][ j ] = dp[ i - 1 ][ j ]
    (3)放进去 dp[ i ][ j ] = dp[ i - 1 ][ j - w[ i ] ] + v[ i ]
    则 dp[ i ][ j ] = max (dp[ i - 1 ][ j - w[ i ] ] + v[ i ], dp[ i - 1 ][ j ]

  3. 初始化
    dp[ 0 ] = 0 非零下标,由于背包是正数背包,并且更新时求max 那么 初始化为正数的最小值 0

  4. 顺序 正序遍历物体,逆序遍历背包
    列表后面的值需要通过与上一层遍历得到的前面的值比较确定
    如果不采用倒序遍历,遍历后一个状态时,要用到前面某个状态的值dp[j-w[i]],而前面的状态值通过正序在本轮遍历已经被覆盖了,而计算后一个状态的值时需要的是覆盖前的值

在这里插入图片描述
416. 分割等和子集

题目:
给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。
分析:
那么只要找到集合里能够出现 sum / 2 的子集总和,就算是可以分割成两个相同元素和子集了。
背包容量为 sum / 2 物品为数组nums 重量为 nums[ i ] 价值为 nums[ i ]
dp[sum/2] == sum/2 表示能装满
一维背包 逆序遍历 dp[j] = max(dp[j], dp[j-nums[i]] + nums[i]);

class Solution {
public:bool canPartition(vector<int>& nums) {int sum = 0;for(int i=0; i<nums.size(); i++){sum += nums[i];}if(sum%2 == 1) return false;int c = sum/2;vector<int>dp(c + 1, 0);for(int i=0; i<nums.size(); i++){for(int j=c; j>=nums[i]; j--){dp[j] = max(dp[j], dp[j-nums[i]] + nums[i]);}}if(dp[c] == c) return true;return false;}
};

http://www.ppmy.cn/news/737091.html

相关文章

前端实战——尚品汇(网页开发)

/* 基础设置 */ .container {width: 1190px;margin: 0 auto; } /* #region顶部导航条start */ .topbar {height: 30px;background-color: #ececec; } .welcome {height: 30px;line-height: 30px;font-size: 0;color: #666; } .welcome span,.welcome a {font-size: 12px; } .we…

《C++ Primer》--学习12

动态内存 动态内存与智能指针 除了静态内存和栈内存&#xff0c;每个程序还拥有一个内存池。这部分内存被称为自由空间 或 堆&#xff0c;程序用堆来存储动态分配的对象 动态内存和智能指针 智能指针负责自动释放所指向的对象 shared_ptr 类 智能指针也是模板

【概率论】随机变量函数的分布

文章目录 选择题 选择题 设随机变量X的分布函数为Fₓ(x),则Y2X1的分布函数为 F Y ( y ) F_Y(y) FY​(y) 是&#xff08;&#xff09; A. F Y ( y ) F x ( 1 2 y − 1 2 ) F_{Y}(y)F_{x} \left ( \frac {1}{2}y- \frac {1}{2} \right ) FY​(y)Fx​(21​y−21​) B. F Y ( y…

tabbar图标大小更改

一,在TabBarItem设计的时候不需要title只要image的时候&#xff0c;如何将image居中显示,做法如下: tabBarItem.imageInsets UIEdgeInsetsMake(5, 0, -5, 0); 特别要注意的是: top和bottom要设置成相反数&#xff0c;不然image的大小会一直改变 二,如果你只是单纯的想改变图片…

电脑如何设置桌面应用图标、图标大小、浏览器网页显示大小

1.桌面应用图标大小 单击桌面空白处&#xff0c;右键 ☞ 查看 ☞ 任意切换大图标、中等图标、小图标 特点&#xff1a;关机重启后失效&#xff0c;再次开机时恢复到默认图标大小 2.浏览器网页、文字大小 Ctrl鼠标滚动 自由缩放当前网页 特点&#xff1a;只应用到当前缩放网页…

如何设置桌面图标大小

如何设置桌面图标大小 首先我们单击鼠标右键&#xff0c; 然后点击查看 点击里面的大图标&#xff0c;中等图标&#xff0c;小图标就可以切换了。我的是中等图标。 希望我的文章能够对你有所帮助。

win10某些软件图标显示过小解决方法

win10笔记本电脑分辨率过高&#xff0c;导致某些没有适配win10的软件显示窗口过小&#xff0c;看起来很是不舒服。 本文将介绍一种解决方法&#xff0c;调大显示窗口及图标。 以My Base为例&#xff1a; 1.右键单击图标–>选择“打开文件所在位置” 2.右键单击图标–>…

Windows软件界面字体和图标太小的解决办法

有时候我们装好软件之后&#xff0c;打开软件会发现部分字体变得非常小&#xff0c;难以看清屏幕中的文字&#xff0c;如图所示&#xff1a; 下面小编在这里以Windows 11系统&#xff08;其余版本Windows系统的设置步骤没有改变&#xff0c;只是部分选项的位置有所改变&#xf…