当前位置: 首页 > news >正文

代码随想录算法训练营第三十五天(20250303) |01背包问题 二维,01背包问题 一维,416. 分割等和子集 -[补卡20250316]

01背包问题 二维

链接

  1. 遍历物品没有大小顺序要求
  2. 重点是模拟,推导出递推公式
#include <iostream>
#include <vector>

int main(){
    int m, n;
    std::cin>>m>>n;
    std::vector<int> weight(m,0),value(m,0);
    for(int i{0}; i<m; i++){
        std::cin>>weight[i];
    }
    for(int i{0}; i<m; i++){
        std::cin>>value[i];
    }
    std::vector<std::vector<int>> dp(m, std::vector<int>(n+1, 0));
    for(int i{0}; i<=n; i++){
        dp[0][i] = i>=weight[0]?value[0]:0;
    }
    for(int i{1}; i<m; i++){
        for(int j{0}; j<=n; j++){
            if(weight[i]<=j){
                dp[i][j] = std::max(dp[i-1][j], dp[i-1][j-weight[i]]+value[i]);
            }else{
                dp[i][j] = dp[i-1][j];
            }
        }
    }
    std::cout<<dp[m-1][n]<<std::endl;
    //
    return 0;
}

01背包问题 一维

链接

  1. 01背包问题可以用一维数组处理,但是需要注意遍历背包的顺序,应该从大到小遍历,因为遍历判断是否应该放入当前物品时,需要比较当前物品放入后剩余空间的最大价值,此时如果当前背包容量大于当前物品空间的两倍,则正序遍历时会将其放入两次,例:dp[j] = max(dp[j], dp[j-weight[i]+value[i]),若当前背包容量为5,物品重量为2,物品价值特别大,则比较未放入当前物品时的价值背包容量为3时的价值与当前物品价值的和,这里假如是从小到大遍历,则在判断容量为3时,因为当前物品价值特别大,已经放入,会与当前再次放入矛盾,导致错误,所以应该从大到小遍历,确保比较时当前物品没有被放入比较过
#include <iostream>
#include <vector>

int main(){
    int m, n;
    std::cin>>m>>n;
    std::vector<int> weight(m,0),value(m,0);
    for(int i{0}; i<m; i++){
        std::cin>>weight[i];
    }
    for(int i{0}; i<m; i++){
        std::cin>>value[i];
    }
    //
    std::vector<int> dp(n+1,0);
    for(int i{0}; i<m; i++){
        for(int j{n}; j>=weight[i]; j--){
            dp[j] = std::max(dp[j], dp[j-weight[i]]+value[i]);
        }
    }
    std::cout<<dp[n]<<std::endl;
    return 0;
}

416. 分割等和子集

  1. 本质上也是01背包问题,相当于每个数字是一个物品,价值和体积都等于数字本身,有一个总和一半大小的背包,要求背包放入物品的价值总和尽量最大,最大是sum/2,如果能达到sum/2,说明可以划分为两个相同大小的子集
class Solution {
public:
    bool canPartition(vector<int>& nums) {
        int sum{0};
        for(const auto& val:nums){
            sum += val;
        }
        if(sum%2!=0){
            return false;
        }
        //
        std::vector<int> dp(sum/2+1,0);
        for(int i{0}; i<nums.size(); i++){
            for(int j{sum/2}; j>=nums[i]; j--){
                dp[j] = std::max(dp[j], dp[j-nums[i]]+nums[i]);
            }
        }
        return dp[sum/2]==sum/2;
    }
};

相关文章:

  • vue-treeselect 【单选/多选】的时候只选择最后一层(绑定的值只绑定最后一层)
  • 热key探测技术架构设计与实践
  • AI战略家:AI政务应用思考——AI与区块链融合对政府权力结构的重构:从“技术赋能”到“制度革命”
  • 音视频入门基础:RTP专题(20)——通过FFprobe显示RTP流每个packet的信息
  • RabbitMQ 基本原理详解
  • mysql数据库中多张表导出成excel方式
  • 【蓝桥杯速成】| 4.递归
  • CTP开发爬坑指北(九)
  • spring声明式事务原理01-调用第1层@Transactional方法(事务访问入口)
  • [蓝桥杯]花束搭配【算法赛】
  • Ubuntu从源码安装Webots
  • 网络编程、URI和URL的区别、TCP/IP协议、IP和端口、URLConnection
  • MySQL相关参数
  • 【C++多线程】thread
  • SDL3 游戏开发 Windows 环境搭建
  • 介绍如何使用YOLOv8模型进行基于深度学习的吸烟行为检测
  • Matlab 矢量控制和SVPWM的感应电机控制
  • 算法——图论——关键活动
  • Blender插件NodeWrangler导入贴图报错解决方法
  • Docker生存手册:安装到服务一本通
  • 做网站旅游销售/公司网站建设哪个好
  • 网站首页html代码/网络推广企划
  • 电商型网站开发多少钱/创意广告
  • 重庆忠县网站建设公司哪里有/如何做好网站的推广工作
  • 建设网站所需材料/优化百度涨
  • 盘石 网站建设/博客网站注册