01背包

01背包问题(回溯法实现,java)

℡╲_俬逩灬. 提交于 2019-12-08 11:29:26
上两天学习的回溯算法,老师让我们回溯法来解决01背包问题, 经过了几天的改改增增,终于实现成功了。 自我感觉回溯算法思想,从左到右,一步一步,能走则走,不能则过! 下面直接贴代码,代码上详细注释! import java.util.Arrays; /** * 回溯法的01背包 * * @author anLA * */ public class BagFBack { private MyElement[] myelements; // 封装的物品 private float s; // 背包容量 private float nowWeight = 0; // 记录当前以拿重量 private float nowPrice = 0; // 记录当前以拿价格 private float betterValue; // 记录最多的价格 /* * 构造方法,用于初始化各个变量 */ public BagFBack(float[] w, float[] v, float s) { myelements = new MyElement[w.length]; for (int i = 0; i < w.length; i++) { myelements[i] = new MyElement(); myelements[i].v = v[i]; myelements[i].w = w[i]; }

AcWing 7.混合背包问题

隐身守侯 提交于 2019-12-04 18:43:38
#include<bits/stdc++.h> using namespace std ; const int N=1010; int n,m; int f[N]; struct Thing { int kind;//记录背包种类 int v,w; }; vector<Thing>things; int main() { cin>>n>>m; for(int i=0; i<n; i++) { int v,w,s; cin>>v>>w>>s; if(s<0) things.push_back({-1,v,w});//01背包 else if(s==0) things.push_back({0,v,w});//完全背包 else {//多重背包 二进制优化 转换为01背包 for(int k=1; k<=s; k*=2) { s-=k; things.push_back({-1,v*k, w*k}); } if(s>0) things.push_back({-1,v*s,w*s}); } } for(auto thing:things) { if(thing.kind<0) {//01背包 for(int j=m; j>=thing.v; j--) f[j]=max(f[j],f[j-thing.v]+thing.w); } else {//完全背包 for(int j=thing.v

第九讲 背包问题问法的变化

匿名 (未验证) 提交于 2019-12-03 00:03:02
以上涉及的各种背包问题都是要求在背包容量(费用)的限制下求可以取到的最大价值,但背包问题还有很多种灵活的问法,在这里值得提一下。但是我认为,只要深入理解了求背包问题最大价值的方法,即使问法变化了,也是不难想出算法的。 例如,求解最多可以放多少件物品或者最多可以装满多少背包的空间。这都可以根据具体问题利用前面的方程求出所有状态的值(f数组)之后得到。 还有,如果要求的是“总价值最小”“总件数最小”,只需简单的将上面的状态转移方程中的max改成min即可。 下面说一些变化更大的问法。 输出方案 一般而言,背包问题是要求一个最优值,如果要求输出这个最优值的方案,可以参照一般动态规划问题输出方案的方法:记录下每个状态的最优值是由状态转移方程的哪一项推出来的,换句话说,记录下它是由哪一个策略推出来的。便可根据这条策略找到上一个状态,从上一个状态接着向前推即可。 还是以01背包为例,方程为 f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]} 。再用一个数组g[i][v],设g[i][v]=0表示推出f[i][v]的值时是采用了方程的前一项(也即f[i][v]=f[i-1][v]),g[i][v]表示采用了方程的后一项。注意这两项分别表示了两种策略:未选第i个物品及选了第i个物品。那么输出方案的伪代码可以这样写(设最终状态为f[N][V]): 另外

01背包问题的变体

匿名 (未验证) 提交于 2019-12-02 23:55:01
维克多博士创造了一个裂变反应堆,可取用处于液体状态的放射性物质。反应堆的容量是V加仑。他有N瓶的放射性液体,每个都有一定的质量和一定的体积。当液体倒入反应堆时,也产生一些单位的能量。现在,维克多想要将能量输出最大化。但是,有一个限制条件。他研究了原子元素的物理知识和历史,认识到反应堆内放射性液体的总量不能超过特定的临界质量M,否则反应就会失控,并引发剧烈的爆炸。 写一个算法,帮助他从反应堆获得最大的能量,而不会让他丢掉性命。 该函数/方法的输入包括六个参数―― reactorCap,一个整数,表示反应堆的容量(V); numberOfRadLiquid,一个整数,表示现有小瓶的数量(N); criticalMass,一个整数,表示反应堆的最大临界质量(M); volumes,一个整数列表,按顺序表示N份放射性液体的体积; masses,一个整数列表,按顺序表示N份放射性液体的质量; energies,一个整数列表,按顺序表示N份放射性液体产生的能量。 返回一个整数,表示可在给定的约束条件下从反应堆中产生的最大能量。 1=<numberOfRadLiquid<=10^4 思路:可以用01背包问题的思路进行求解。 关于01背包问题的详细解析,可参考https://blog.csdn.net/mu399/article/details/7722810。 本题的阶梯代码如下: int

回滚线段树+bitset优化01背包――cf981E

匿名 (未验证) 提交于 2019-12-02 23:48:02
/*首先考虑如何计算一个点的可能凑出的值,这就是一个01可行性背包问题那么再拓展到一段区间[1..n]的点上,每个query都可以看做是一段区间上的点[l,r]加上一个体积为x的物品,转换到01背包上就是进行一次更新那么用线段树来维护每个query的区间更新 每个位置(区间)维护一个bitset,每次加入a都进行一次01背包 用线段树来维护区间的bitset,表示一段区间能组成的值 但是没法用lazy,每次区间更新只能停留在一段区间可以把每次停留在区间的数a用vector保存下来,当进行完所有的更新时,从线段树叶子结点开始向上回滚每个区间的可行性是左儿子的可行性|右儿子的可行性|vector里存的每个a提供的可行性贡献 */ #include<bits/stdc++.h> using namespace std; int n,m; #define maxn 10005 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 struct Node{int l,r,x;}p[maxn]; bitset<10005>seg[maxn<<2]; vector<int>v[maxn<<2]; void build(int l,int r,int rt){ seg[rt][0]=1; if(l==r)return; int m=l+r>>1;

01背包问题

痞子三分冷 提交于 2019-12-02 11:01:07
思路 首先再说01背包问题之前,先要了解一个概念,就是多阶段决策问题,我们都知道,对于动态规划来说核心就是状态的定义和状态转移方程,对于多阶段决策问题,阶段就对应状态,而01背包问题就是多阶段决策问题,核心就是找到状态转移方程。 想法 一开始看到背包问题很自然都就想到了贪心算法,但是对于01背包问题,是不适用的,因为贪心算法解决的背包问题中物品是可以取一部分的,所以才能尽可能的把‘’密度‘’比较大的物品放入背包,而01背包问题只有一个物品,且要么放入,要么不放入,就不能用贪心算法。 改变 既然贪心算法不适用,那么我们来想想用动态规划解决问题,因为对于每一个物品来说,有一个决策——放入或者不放入,那么首先我们要确定状态,如果我们把每一个剩余体积当作一个状态行不行呢?回想一下之前讲过的“硬币问题”,也是将每一个剩余金额作为一个状态,但是在这里是不适用的,为什么?因为硬币问题的决策判断条件是剩余金额大于等于硬币面值,但是这里却多了一个条件,就是每一个物品只能取一次,这样状态转移方程就不好写了。 这里我们引入“阶段”的概念,从第1个物品到第n个物品扫描,将每一次扫描的移动作为一次阶段,对于每一个阶段,决策就是对该阶段的物品的取或不取,解为d[i][j],表示对于第i个阶段, 分类: 1.如果剩余的体积小于物品体积,就不取,那么d[i][j]=d[i-1][j], 2

01背包思想和优化

♀尐吖头ヾ 提交于 2019-12-02 08:49:49
dp入门问题: 01背包装下了我们的忧伤QWQ    作为一枚乐于作死...呸,乐于学习的蒟蒻,当然要学会装包的 那么 简单的描述一下01背包问题:   小明有个bag,容量是m.小明面前有n个物品,每个物品有它的价值vi和它的体积wi,小明想知道用这个背包能装到的物品总价值最大是多少. 好,这就是一个最朴素的01背包问题,那么怎么解决呢. 稍加思索...dp嘛,从小问题解决到大问题.我们用一个数组dp[i][j]表示选第i件物品时容量为j可以得到的最大价值。 状态转移方程就出来啦: dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+[v[i]]); 其实01背包过程就是 选与不选第i件物品, dp[i-1][j]实则就是不选第i件物品, dp[i-1][j-w[i]]+v[i]就是选了第i件物品,既然我们选了,那就要减掉它的wi再加上它的价值vi。然后在两者之间选最优方案就完美解决了 总的来说:01背包就是靠着第i-1的状态更新第i的状态 上代码: 再次开启脑洞:我们发现更新第i件物品的时候只需要用到第i-1的状态,之前的状态都可以抛弃,这样我们就可以 抛弃i这个维度,只用一个维度保存j ,这样做的的话,代码就变成了这样 注意这必须是逆序遍历,至于为什么呢?上面已经说过, 01背包就是靠着第i-1的状态更新第i的状态 ,如果顺序遍历的话

树形依赖的背包 树形dp

元气小坏坏 提交于 2019-12-01 13:43:07
树形DP有一个独特的优化,就是通过递归,枚举目前有效的元素个数,求dp[ i ][ j ] (表示 选取以i为根的子树中有选取j个元素的最大取值) (搭配 siz 数组表示当前该节点的总共子孙数) 1. hdu1561 (树形依赖背包裸题) 注意 siz 数组的运用,以及 u 点选择的节点数时要逆向枚举,就像01背包 复杂度看似O(n^3),实际是 O( n^2 ) 左右。 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> using namespace std; const int maxn = 250; vector<int> g[maxn]; int dp[maxn][maxn]; int val[maxn]; int siz[maxn]; int n,m; //dp[i][j] 表示 选取以i为根的子树中有选取j个元素的最大取值 void dfs(int u){ siz[u]=1; dp[u][1] = val[u]; for(int i=0; i<g[u].size(); i++){ int v = g[u][i]; dfs(v); //这里的siz[u]不包括siz[v] ,并且是把效率很低的2^n举法用01背包来做 for

第九讲 背包问题问法的变化

若如初见. 提交于 2019-11-29 09:37:26
以上涉及的各种背包问题都是要求在背包容量(费用)的限制下求可以取到的最大价值,但背包问题还有很多种灵活的问法,在这里值得提一下。但是我认为,只要深入理解了求背包问题最大价值的方法,即使问法变化了,也是不难想出算法的。 例如,求解最多可以放多少件物品或者最多可以装满多少背包的空间。这都可以根据具体问题利用前面的方程求出所有状态的值(f数组)之后得到。 还有,如果要求的是“总价值最小”“总件数最小”,只需简单的将上面的状态转移方程中的max改成min即可。 下面说一些变化更大的问法。 输出方案 一般而言,背包问题是要求一个最优值,如果要求输出这个最优值的方案,可以参照一般动态规划问题输出方案的方法:记录下每个状态的最优值是由状态转移方程的哪一项推出来的,换句话说,记录下它是由哪一个策略推出来的。便可根据这条策略找到上一个状态,从上一个状态接着向前推即可。 还是以01背包为例,方程为 f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]} 。再用一个数组g[i][v],设g[i][v]=0表示推出f[i][v]的值时是采用了方程的前一项(也即f[i][v]=f[i-1][v]),g[i][v]表示采用了方程的后一项。注意这两项分别表示了两种策略:未选第i个物品及选了第i个物品。那么输出方案的伪代码可以这样写(设最终状态为f[N][V]): 另外

01背包问题的变体

守給你的承諾、 提交于 2019-11-28 13:48:24
题目描述 维克多博士创造了一个裂变反应堆,可取用处于液体状态的放射性物质。反应堆的容量是V加仑。他有N瓶的放射性液体,每个都有一定的质量和一定的体积。当液体倒入反应堆时,也产生一些单位的能量。现在,维克多想要将能量输出最大化。但是,有一个限制条件。他研究了原子元素的物理知识和历史,认识到反应堆内放射性液体的总量不能超过特定的临界质量M,否则反应就会失控,并引发剧烈的爆炸。 写一个算法,帮助他从反应堆获得最大的能量,而不会让他丢掉性命。 输入 该函数/方法的输入包括六个参数—— reactorCap,一个整数,表示反应堆的容量(V); numberOfRadLiquid,一个整数,表示现有小瓶的数量(N); criticalMass,一个整数,表示反应堆的最大临界质量(M); volumes,一个整数列表,按顺序表示N份放射性液体的体积; masses,一个整数列表,按顺序表示N份放射性液体的质量; energies,一个整数列表,按顺序表示N份放射性液体产生的能量。 输出 返回一个整数,表示可在给定的约束条件下从反应堆中产生的最大能量。 约束条件 1=<numberOfRadLiquid<=10^4 思路:可以用01背包问题的思路进行求解。 关于01背包问题的详细解析,可参考https://blog.csdn.net/mu399/article/details/7722810。