白话背包之完全背包

借着前面的  白话背包之01背包 的基础,来结合图看看完全背包是个什么东东,希望以后自己看能一目了然,能对刚接触的童鞋有帮助是最好不过滴

一:关于完全背包

有N个物品,每个物品(有无限多个) i 对应有重量w[i]、价值va[i]。有一个背包可以放M重的物品,现在让你从N钟物品中选择一些物品,在不超过背包上限情况使得背包装的价值最大。

二:初步了解完全背包算法

那么这里看看状态转移方程:

dp[i][j]=max{dp[i-1][j-k*w[i]]+k*va[i] | 0<=k*va[i]<=M},理解为在考虑第i件物品的时候,背包剩余容量为j下获得的最大利益。

看看代码:解释清楚再优化

for(int i = 1; i <= N; i ++){
    for(int j = w[i]; j <= M; j ++){
        int Max = 0;
        for(int k = 0; k*w[i] <= M; k ++){
            Max = max(Max,dp[i-1][j-k*w[i]]+k*va[i]);
        }
        dp[i][j] = Max;
    }
}

那么我们看看这是怎么运算的,例如,第一件物品w[1] = 3, va[1] = 2;那么我们对于上面的代码,如下图执行:

那么先考虑 dp[1][3]的情况,我们发现,在这里,k循环的时候只能取 1,使得dp[1][3] = dp[0][3-1*3]+1*2 = dp[0][0]+2 = 2;意思是,考虑第一件物品,背包大小为3的情况,我们能放1个第一件物品(多了就放不下啦),使得这个状态下收益最大。

那么同理,考虑第一件物品的时候,背包的其他状态更新如下:

可以发现,一直到背包容量为6之前,都只可以放下一个第一件物品,那么容量为6的时候,刚好就可以放进两个

那么这里我们就可以发现,其实第一件物品、容量为6的状态dp[1][6],可以在dp[1][3]的状态得到,并且其他的状态也类似。。。

三:那么我们可以引入优化的一维数组,同时也降低时间复杂度

先看看一维数组的算法:

for(int i = 1; i <= N; i ++){
    for(int j = w[i]; j <= M; j ++){
        dp[j] = max(dp[j],dp[j-w[i]]+va[i]);
    }
}

上面说其他状态类似,到底怎么类似的呢?,看图:

那么,到6之前就变成了

那么更新 dp[6]的时候,就可以依靠dp[3]+va[1] 得到,那么在考虑其他的物品的时候,也就类似啦。那么这里也就是需要区别01背包的地方。。。就是for循环的时候,是从小到大,因为考虑当前状态dp[j]的时候,我们是必须依靠前面已有的状态 (也就是,前面一定放了这件物品,我们再放一件,看能不能得到更大利益)
来更新现在的状态。

OK,到此完全背包完毕

个人愚昧观点,欢迎指正与讨论

白话背包之完全背包

时间: 2024-10-18 10:40:13

白话背包之完全背包的相关文章

白话背包之全然背包

借着前面的  白话背包之01背包 的基础,来结合图看看全然背包是个什么东东,希望以后自己看能一目了然,能对刚接触的童鞋有帮助是最好只是滴 一:关于全然背包 有N个物品,每一个物品(有无限多个) i 相应有重量w[i].价值va[i].有一个背包能够放M重的物品,如今让你从N钟物品中选择一些物品,在不超过背包上限情况使得背包装的价值最大. 二:初步了解全然背包算法 那么这里看看状态转移方程: dp[i][j]=max{dp[i-1][j-k*w[i]]+k*va[i] | 0<=k*va[i]<

有关货币问题的动态规划题目--有关01背包,完全背包,多重背包

背包dp:参考背包九讲以及给出一些题目 01背包 (先枚举物品,再逆序枚举容量) 给定n件物品和一个容量为V的背包,每件物品的体积是w[i],价值是va[i](1<=i<=n),求在不超过背包的容量的情况下,怎么选择装这些物品使得得到的价值最大? 例如:有5件物品,体积分别是{2,2,6,5,4},价值分别是{6,3,5,4,6} 递归式:F(i,v)=max(F(i-1,v), F(i-1,v-w[i])+va[i]),其中F(i,v)表示把前i种物品恰放入背包容量为v时取得的最大价值 把这

多重背包转换成完全背包和01背包

void CompletePack(int cost,int weight)   多重背包 { for(int i=cost;i<=m;i++) dp[i]=max(dp[i],dp[i-cost]+weight); } void ZeroOnePack(int cost,int weight)    01背包 { for(int i=m;i>=cost;i--) dp[i]=max(dp[i],dp[i-cost]+weight); } void MultiplyPack(int cost,

HDU 3033 I love sneakers! (01背包+反分组背包)

题意:给你 n,m,k,表示有k种鞋子共n双,你有m的容量: 每双鞋子有容量p和价值v:问是否买全k种鞋子,若能在容量为m的情况下最多能买到鞋子的价值为多少: 每双鞋子只能买一次(01背包),每种鞋子至少买一种(分组背包:每组只能有一个)与传统分组背包的限制相反. 注意初始化!!! #include<cstdio> #include<stdlib.h> #include<string.h> #include<string> #include<map&g

【背包问题】0-1背包、完全背包、多重背包、混合三种背包、二位费用背包、分组背包

一.0-1背包问题 输入:第一行物品的个数n,第二行背包的质量m,随后n行每行给出每个物品的重量和价值,每种物品只有一个. 输出:背包可以达到的最大价值 样例输入: 5 10 1 5 2 4 3 3 4 2 5 1 样例输出: 14 动态规划的过程中需要逆序,因为如果不是逆序那么 当i=0的时候 f[0]=0; f[1]=max(f[1],f[1-w[0]]+v[0])=5; f[2]=max(f[2],f[2-w[0]]+v[0])=10; f[3]=max(f[3],f[3-w[0]]+v[

【算法学习笔记】30.动态规划 01背包和完全背包的关系

首先先说明一下01背包和完全背包问题的区别 01背包:有 N 件物品和一个容量为 V 的背包.放入第 i 件物品耗费的费用是 Ci,得到的价值是 Wi.求解将哪些物品装入背包可使价值总和最大.(可以不装满) 完全背包:有 N 种物品和一个容量为 V 的背包,每种物品都有无限件可用.放入第 i 种物品 的费用是 Ci,价值是 Wi.求解:将哪些物品装入背包,可使这些物品的耗费的费用总和不超过背包容量,且价值总和最大. 先说结论: 两个问题的最优解都要用DP来解决,实现的过程也非常像只是在内层循环中

背包之01背包、完全背包、多重背包详解

首先说下动态规划,动态规划这东西就和递归一样,只能找局部关系,若想全部列出来,是很难的,比如汉诺塔.你可以说先把除最后一层的其他所有层都移动到2,再把最后一层移动到3,最后再把其余的从2移动到3,这是一个直观的关系,但是想列举出来是很难的,也许当层数n=3时还可以模拟下,再大一些就不可能了,所以,诸如递归,动态规划之类的,不能细想,只能找局部关系. 1.汉诺塔图片 (引至杭电课件:DP最关键的就是状态,在DP时用到的数组时,也就是存储的每个状态的最优值,也就是记忆化搜索) 要了解背包,首先得清楚

01背包、完全背包

01背包 问题描述 有n个重量(费用)和价值分别为wi,vi的物品.从这些物品中挑选出总重量(费用)不超过W的物品,求所有挑选方案中价值总和的最大值. 例子 n=4 (w,v)={(2,3),(1,2),(3,4),(2,2)} W=5 输出:7 1 二维数组版:时间复杂度O(nW) ,空间复杂度O(nW) 记得以下所有方法首先都要初始化dp数组memset(dp,0,sizeof(dp)); dp[i][j] :表示从前i个物品中选出总重量不超过j的物品时总价值的最大值. int dp[MAX

背包整理(01背包,完全背包,多重背包,分组背包)(待更新)

目录 01背包 优化(空间) 完全背包 优化 多重背包 优化 分组背包 01背包 有N件物品和一个容量为V的背包.第i件物品的价格(即体积,下同)是w[i],价值是c[i].求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大. 对于每个物品,我们有两种选择:把这个物品放进背包还是不放. d[i][v]表示前i件物品,恰放入容积为v的背包时的价值总和. 状态转移方程为 \[d[i][v] = \max(d[i - 1][v],d[i - 1][v - w[i]] + c[i