首页 > 其他分享 >代码随想录——动态规划01背包

代码随想录——动态规划01背包

时间:2024-12-29 11:08:26浏览次数:5  
标签:vector 遍历 cost int 随想录 value 01 背包 dp

image

暴力:每一件物品其实只有两个状态,取或者不取,所以可以使用回溯法搜索出所有的情况,那么时间复杂度就是O(2^n),这里的n表示物品数量。
所以暴力的解法是指数级别的时间复杂度。进而才需要动态规划的解法来进行优化!

二维dp数组01背包

  1. 确定dp数组及下标含义
    dp[i][j]表示前i件物品恰放入一个容量为j的背包可以获得的最大价值。
    此时最后返回dp[n-1][w]即可

  2. 确定递推公式
    dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);
    解释:从“不放入第i件物品”与“放入第i件物品的价值 + 放入前i-1件物品到容量为j-weight[i]的背包可获得的最大价值”中选最大值

  3. dp数组初始化

    1. 容量为0时,都为0
    2. 因为dp[i][j]需要用到dp[i-1][j],所以需要初始化第一行。
      当j>=weight[0]时,dp[0][j]应该是value[0];否则是0.

关于初始化,一定要和dp数组的定义吻合,否则到递推公式的时候就会越来越乱。
image

  1. 确定遍历顺序
    先遍历物品再遍历容量 或相反都可以。因为递推公式用到的都是dp[i][j]左上的元素。

代码

#include<iostream>
#include<vector>
 
using namespace std;
 
int main(){
    int M,N;
    cin>>M>>N;
    vector<int> value(M);
    vector<int> cost(M);
    for(int i=0;i<M;i++){
        cin>>cost[i];
    }
    for(int i=0;i<M;i++){
        cin>>value[i];
    }
    vector<vector<int>> dp(M,vector<int>(N+1,0));//dp[M][N]是从0到M-1个材料中选择,容量为N时的最大价值
     
    //初始化
    for(int j=cost[0];j<=N;j++){
        dp[0][j] = value[0];
    }
    for(int i=1;i<M;i++){
        for(int j=0;j<=N;j++){
            if(j<cost[i])dp[i][j] = dp[i-1][j];
            else dp[i][j] = max(dp[i-1][j],dp[i-1][j-cost[i]]+value[i]);
        }
    }
    cout<< dp[M-1][N];
     
    return 0;
}

一维dp数组01背包

二维递推公式dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);
发现如果把dp[i - 1]那一层拷贝到dp[i]上,表达式完全可以是:dp[i][j] = max(dp[i][j], dp[i][j - weight[i]] + value[i]);

区别在于遍历顺序。

  1. 容量只能从大到小遍历。
    如果从小到大,上一层的dp[j]会被覆盖,导致后续计算dp[i][j-weight[i]]时使用的是这一层的dp而出现错误。如果从大到小遍历,因为递推公式不会用到
  2. 只能先遍历物品再遍历容量
    因为容量从大到小遍历,如果先遍历容量再遍历物品。算不出答案。
#include<iostream>
#include<vector>

using namespace std;

int main(){
    int M,N;
    cin>>M>>N;
    vector<int> value(M);
    vector<int> cost(M);
    for(int i=0;i<M;i++){
        cin>>cost[i];
    }
    for(int i=0;i<M;i++){
        cin>>value[i];
    }
    
    // 一维数组
    vector<int> dp(N+1,0);
    //初始化
    for(int j=cost[0];j<=N;j++){
        dp[j] = value[0];
    }
    //遍历顺序——容量从后往前
    for(int i=1;i<M;i++){
        for(int j=N;j>=cost[i];j--){
            dp[j] = max(dp[j],dp[j-cost[i]]+ value[i]);
        }
    }
    cout << dp[N];
    return 0;
}

标签:vector,遍历,cost,int,随想录,value,01,背包,dp
From: https://www.cnblogs.com/neromegumi/p/18638532

相关文章

  • 【PR2025】Adobe Premiere Pro 专业视频编辑软件下载安装(2017-2025win/mac)
    软件简介AdobePremierePro(简称PR) 是Adobe公司推出的一款专业视频编辑软件,广泛应用于影视制作、广告制作以及个人创作等领域。该软件具备强大的视频编辑功能,支持多种视频格式,提供灵活的编辑工具和高效的工作流程,帮助用户制作出高质量的视频作品。下载链接https://pa......
  • SOCS0100 Computational Tools
    SOCS0100 Computational Tools for Reproducible Social ScienceSecond Summative AssignmentGuidelines for Completing and Submitting SOCS0100 Assignment:•Thisassessmentisdueon 13 January 2025, 1pm and shallbe submitted on Moodle.......
  • [PA2019] Desant Solution
    [PA2019]DesantSolution原题链接。题目大意:给定一个长为\(n(n\le40)\)的排列,对于每个\(i\)求出长度为\(i\)的子序列逆序对最少有多少,并且求出有多少个长度为\(i\)的子序列逆序对最少。解题思路:首先有一个暴力的做法,设\(f_{i,S}\)表示考虑完前\(i\)个数,选择了集......
  • 学习012-02-03-14 How to: Reorder an Action Container‘s Actions Collection(如何:对
    Howto:ReorderanActionContainer’sActionsCollection(如何:对操作容器的操作集合进行重新排序)InanXAFapplicationUI,ActionsarelocatedwithinActionContainers.YoucanusetheActionBase.CategorypropertyandtheApplicationModel’sActionDesign......
  • Java难绷知识01——IO流的对象流
    Java难绷知识01之对象流本篇文章会探讨一些JavaIO流中比较容易被忽视的对象流,而且会相对的探讨其中的一些细节其中对于对象流的操作讲解会少一些,主要讨论的是一些细节在JavaIO流中,对象流(ObjectInputStream对象输入流和ObjectOutputStream对象输出流)用于将对象进行序列化和......
  • 【电力】3D空间桁架电力传输塔FEM分析【含Matlab源码 10011期】复现
    ......
  • 打卡信奥刷题(500)用C++信奥P6496[普及组/提高] [COCI2016-2017#2] Nizin
    [COCI2016-2017#2]Nizin题目描述设AAA是一个含有nnn个元素的......
  • DP优化——树上依赖性背包&P6326 Shopping
    P6326Shopping题意等价于要买一个连通块。首先如果我们能求出一个dp数组:\(f_{i,j}\)表示\(i\)子树内,有\(j\)元,一定要选\(i\),能得到的最大价值。那么\(f_{1,m}\)就是一定选根的答案。然后点分治即可。接下来就是怎么在合理的复杂度内求出dp数组。直接背包显然......
  • 01 _ 认识容器:容器的基本操作和实现原理
    01_认识容器:容器的基本操作和实现原理你好,我是程远。作为一名工程师,我猜在过去的几年时间里,你肯定用过或者听人提起过容器(Container)。说实话,容器这东西一点都不复杂,如果你只是想用的话,那跟着Docker官网的说明,应该十来分钟就能搞定。简单来说,它就是个小工具,可以把你想跑的......
  • 01 _ 认识容器:容器的基本操作和实现原理
    01_认识容器:容器的基本操作和实现原理你好,我是程远。作为一名工程师,我猜在过去的几年时间里,你肯定用过或者听人提起过容器(Container)。说实话,容器这东西一点都不复杂,如果你只是想用的话,那跟着Docker官网的说明,应该十来分钟就能搞定。简单来说,它就是个小工具,可以把你想跑的......