笔记:代码随想录算法训练营第35天: 01背包问题 二维、 01背包问题 一维 、LeetCode416. 分割等和子集

学习资料:代码随想录

这一块儿学得挺痛苦

注:文中含大模型生成内容

动态规划:01背包理论基础

卡码网第46题

思路:五部曲

定义:dp[i][j]为第i个物品背包容量为j,能装下的最大价值

递推公式:dp[i][j]的值等于dp[i-1][j]的值和dp[i-1][j-weight[i]]+value相比的最大值,后者为看放下当前物品+减去当前物品的容量能放下什么价值,当然,要是放不下当前物品,就算了,保持原来的值把

初始化:左边(dp[i][0]背包容量为0)都初始化为0,挺好的,就是不用管了

dp[0][j],容量j能把物品0放上就放上,放不上就是0

遍历顺序:怎么着都行

打印:略

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
 
int main(){
    int materials,N;
    cin>>materials>>N;
    vector<int> space(materials,0);
    for(int i=0;i<materials;i++){
        cin>>space[i];
    }
 
    vector<int> value(materials,0);
    for(int i=0;i<materials;i++){
        cin>>value[i];
    }
 
    vector<vector<int>> dp(materials,vector<int>(N+1,0));    //dp[i][j]表示有i个材料可以放,背包能装的空间为j时的最大价值,从行李空间为0开始递推
 
    for(int j=space[0];j<=N;j++) dp[0][j] = value[0];
 
    for(int i=1;i<materials;i++){     //i从1开始,否则在递推函数处会索引负数
        for(int j=0;j<=N;j++){
            if(j<space[i]) dp[i][j] = dp[i-1][j];       //防止下面出现负索引
            else{
            dp[i][j] = max(dp[i-1][j],dp[i-1][j-space[i]]+value[i]);  //递推公式得画图模拟一下
            }
        }
    }
    cout << dp[materials-1][N]<<endl;    //第materials个物品下标为materials-1   
 
}

动态规划:01背包理论基础(滚动数组)

卡码网第46题

滚动数组是把原先的二维dp数组压缩成一维了,就等于看新一个物品能不能装上的时候就按规矩累计之前的结果然后把之前的覆盖掉

主要在遍历方向上很难:

一是j要倒着遍历:

TA说得很清楚:二维是根据上一个物品更新的。而一维数组是在本行根据本物品更新的。正序的化就会产生能多次放该物品的错觉,实际上该物品只能放一次

为什么不能先遍历背包,还是让TA帮我模拟一下,不行啊,先遍历背包的话只能加上一个物品。

啊,这不就是我的贾维斯吗!!我能获得一份开发贾维斯的工作吗

我自己模拟了一下正向遍历j在外层,不行,会出现重复放一个物品的问题。总之,根据递推公式来看,还是要提取上一轮的信息,不要让上一轮的信息被本轮信息覆盖

416. 分割等和子集

力扣题目链接

思路:关键在于如何将其转换为背包问题;

dp[j]为背包容量为j,能装的最大价值,那么在这里,,value[i]和weight[i]都是nums[i];背包容量是数字和的一半sum/2,是那个target,如果背包容量target能装target,就是能对半儿分了

cpp 复制代码
// 五部曲
// dp定义:dp[j] 容量为j的背包,能装的价值为dp[j]
// 递推公式:按背包来,价值和重量都是这个数的值
// 初始化:根据递推公式的max要选最大的,nums都是正整数,所以都初始化为最小的正整数0
// 遍历顺序:按背包来
// 打印
class Solution {
public:
    bool canPartition(vector<int>& nums) {
        vector<int> dp(100*200/2+1);   //根据题意区间写的
        int sum = 0;
        for(int num:nums){
            sum+=num;
        } 

        if (sum%2!=0) return false; 
        int target = sum/2;

        for(int i=0;i<nums.size();i++){
            for(int j=target;j>=nums[i];j--){
                dp[j] = max(dp[j],dp[j-nums[i]]+nums[i]);
            }
        }
        return dp[target] == target;
    }
};

https://www.youtube.com/watch?v=bI_GJHCePlY今日发现一件艺术品,搁5、6年前我可能是他们的受众,现在的我没有耐心连着看第三遍了。Anyway,祝大家今晚睡个好觉,明天是Sunday Morning哦

相关推荐
姜行运4 分钟前
数据结构【红黑树】
数据结构·c++·c#
TechCampus14 分钟前
小红书面试中我这样解释 KMP,面试官点头了
算法
Youndry17 分钟前
验证二叉搜索树
算法
Spider_Man19 分钟前
从 "字符拼图" 到 "文字魔术":动态规划玩转字符串变形术
javascript·算法·leetcode
玄妙尽在颠倒间38 分钟前
雪花算法:从 64 位到 128 位 —— 超大规模分布式 ID 生成器的设计与实现
后端·算法
Star在努力1 小时前
15-C语言:第15~16天笔记
c语言·笔记·算法
CoovallyAIHub1 小时前
工业质检新突破!YOLO-pdd多尺度PCB缺陷检测算法实现99%高精度
深度学习·算法·计算机视觉
gb42152871 小时前
负载均衡算法中的加权随机算法
windows·算法·负载均衡
RXXW_Dor2 小时前
数据结构之线性表
数据结构
xdlka2 小时前
C++初学者4——标准数据类型
开发语言·c++·算法