动态规划(01背包和完全背包系列)

1. 背包问题总结模板

这两道题分别是动态规划中背包问题的一种,我们可以大致把背包问题分为01背包和完全背包以及组合背包问题
1.

  • 01背包问题就是:从n个物品中选取当容积达到m的时候,背包此时的价值最大。但是背包中每种物品只能选取一次
  • 完全背包则是:此时从n个物品中选取当容积达到m的时候,背包的此时价值最大,但是每种物品都可以重复选取
  • 组合背包(组合和排列)问题:此时我们需要对背包中的物品要考虑顺序(然而这一种才是最应该好好思考的,因为他的遍历顺序是有严格的方式的,如果我们选择了不恰当的遍历方式,这里是会报错的,对于排序问题我们应该选择先遍历容积在遍历物品,对于组合问题我们依旧选择和别的方式一样的先遍历物品在遍历,为什么要这样呢?那是因为如果我们在排序哪里依旧使用原来的遍历顺序,是会出现重复的结果的,比如说{1,5}和{5,1},在组合里面这两个结果算一个,但是在排序里面这算两个结果

2.首先是背包分类的模板

  • 1、0/1背包:外循环nums,内循环target,target倒序且target>=nums[i];
  • 2、完全背包:外循环nums,内循环target,target正序且target>=nums[i];
  • 3、组合背包(考虑顺序):外循环target,内循环nums,target正序且target>=nums[i];
  • 4、分组背包:这个比较特殊,需要三重循环:外循环背包bags,内部两层循环根据题目的要求转化为1,2,3三种背包类型的模板(待定)

3.问题分类的模板

  • 1、最值问题: dp[i] = max/min(dp[i], dp[i-nums]+1)或dp[i] = max/min(dp[i], dp[i-num]+nums);
  • 2、存在问题(bool):dp[i]=dp[i]||dp[i-num];
  • 3、组合问题:dp[i]+=dp[i-num];

2. 01背包系列题目

2.1 LintCode—01背包问题

链接:https://www.lintcode.com/problem/125/
在这里插入图片描述
题解:
在这里插入图片描述
仔细感觉就会发现其实是在填这个物品和容积所构成的一个表格(一定要对于物品和容量所开辟的表格多开一行一列,这样做的目的也是为了能够直接进行初始化),最终需要返回的是dp[n][m],也就是从前n个物品当中任意选择物品,且体积总和不超过m的最大价值

class Solution{
   
public:
 int backPackII(int m, vector<int> &A, vector<int> &V) {
   
        // write your code here
        int n = A.size();
        vector<vector<int>> dp(n+1,vector<int>(m+1,0));
        for(int i = 1;i<=n;++i)
        {
   
            for(int j = 1;j<=m;++j)
            {
   
                if(A[i-1] > j)
                {
   
                    //肯定是放不下的
                    dp[i][j] = dp[i-1][j];
                }
                else
                {
   
                    dp[i][j] = std::max(dp[i-1][j-A[i-1]]+V[i-1],dp[i-1][j]);
                }
            }
        }
        return dp[n][m];
    }
};

2.2 LeetCode第416题—分割等和子集(存在问题)

在这里插入图片描述
这道题和sum和一样,如何找到这道题是一道01背包问题,是这道题的关键。

class Solution {
   
public:
    //left - right = 0;
    //left + right = sum;
    //2left = sum           ->      left = sum/2
    bool canPartition(vector<int>& nums) {
   
        int sum = 0;
        for(int& e: nums)
            sum += e;
        if(sum % 2 == 1)
            return false;
        int bigSize = sum /2;
        vector<vector<int>> dp(nums.size()+
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值