背包问题

DP---DAG、背包、LIS、LCS

为君一笑 提交于 2019-12-10 04:04:56
DP是真的难啊,感觉始终不入门路,还是太弱了┭┮﹏┭┮ DAG上的DP ​ 一般而言,题目中如果存在明显的 严格偏序 关系,并且求依靠此关系的 最大 / 最小 值,那么考虑是求DAG上的最短路或者是最长路。(据说还有路径计数的问题,我倒是没遇到,哪位大大看见提醒一下呐) 这类问题可以使用记忆化搜索直接解,但是有 爆栈 的风险。 数据比较大的情况下,可以使用先求 拓扑序 ,然后按照拓扑序(bfs求拓扑序),进行递推即可。 背包问题 ​ 1.完全背包 for (int i = 1; i <= n; i++) for (int j = w[i]; j <= m; ++j) f[j] = max(f[j],f[j - w[i]] + v[i]); 完全背包本质就是一个DAG问题,把背包的剩余容量看成状态,边就是物品的体积。 ​ 2.01背包 for (int i = 1; i <= n; i++) for (int j = 0; j <= m; j++) if (j < w[i]) f[i][j] = f[i-1][j]; else f[i][j] = max(f[i-1][j],f[i-1][j-w[i]] + v[i]); ​ 简化后 for (int i = 1; i <= n; i++) for (int j = w[i]; j <= m; ++j) f[j] = max(f[j]

01背包算法

时光总嘲笑我的痴心妄想 提交于 2019-12-10 03:55:35
转: 01背包问题 动态规划的基本思想: 将一个问题分解为子问题递归求解,且将中间结果保存以避免重复计算。通常用来求最优解,且最优解的局部也是最优的。求解过程产生多个决策序列,下一步总是依赖上一步的结果,自底向上的求解。 动态规划算法可分解成从先到后的4个步骤: 1. 描述一个最优解的结构,寻找子问题,对问题进行划分。 2. 定义状态。往往将和子问题相关的各个变量的一组取值定义为一个状态。某个状态的值就是这个子问题的解(若有 k个变量,一般用 K维的数组存储各个状态下的解,并可根 据这个数组记录打印求解过程。)。 3. 找出状态转移方程。一般是从一个状态到另一个状态时变量值改变。 4.以“自底向上”的方式计算最优解的值。 5. 从已计算的信息中构建出最优解的路径。(最优解是问题达到最优值的一组解) 其中步骤1~4是动态规划求解问题的基础,如果题目只要求最优解的值,则步骤5可以省略。 背包问题 01背包: 有N件物品和一个重量为M的背包。(每种物品均只有一件)第i件物品的重量是w[i],价值是p[i]。求解将哪些物品装入背包可使价值总和最大。 完全背包: 有N种物品和一个重量为M的背包,每种物品都有无限件可用。第i种物品的重量是w[i],价值是p[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包重量,且价值总和最大。 多重背包: 有N种物品和一个重量为M的背包

背包(0-1)问题

∥☆過路亽.° 提交于 2019-12-09 18:18:07
背包容量是C,可容纳N件商品,每件商品要么放要么不放,商品的重量数组W[ ],价值数组V[ ]。 通过动态规划算法,建立矩阵M[N][C]。 M[i][j]的含义为,往背包里放从0-i的物品的最大价值,j为背包容量。 M[i][j]的有两种选择:一是,不放当前物品i,M[i-1][j];二是,放当前物品i,则值为 V[i]+M[i-1][j-W[i]]。也就是当前物品的价值加上,背包容量为j-W[i],放0-i-1物品的最大价值。 矩阵里的每个值都是子问题的最优解,也就是背包在容量为j,容纳物品为0-i的最大价值。 还有一个问题,如何判定装入了哪个物品,由矩阵生成过程,可以知道,当M[i][j] != M[i-1][j]时,放入了物品i。以此类推,可以得到所有放入背包中的物品。 来源: CSDN 作者: anjingjingg 链接: https://blog.csdn.net/anjingjingg/article/details/103461763

彻底理解0-1背包问题

南楼画角 提交于 2019-12-08 11:31:27
0-1背包问题 给定n个重量为 w 1 w_1 w 1 ​ , w 2 w_2 w 2 ​ , w 3 w_3 w 3 ​ ,…, w n w_n w n ​ ,价值为 v 1 v_1 v 1 ​ , v 2 v_2 v 2 ​ , v 3 v_3 v 3 ​ ,…, v n v_n v n ​ 的物品和容量为 C C C 的背包,求这个物品中一个最有价值的子集,使得在满足背包的容量的前提下,包内的总价值最大 0-1背包问题指的是每个物品只能使用一次 递归方法 首先我们用递归的方式来尝试解决这个问题 我们用 F ( n , C ) F(n,C) F ( n , C ) 表示将前 n n n 个物品放进容量为 C C C 的背包里,得到的最大的价值。 我们用自顶向下的角度来看,假如我们已经进行到了最后一步(即求解将 n n n 个物品放到背包里获得的最大价值),此时我们便有两种选择 不放第 n n n 个物品,此时总价值为 F ( n − 1 , C ) F(n-1,C) F ( n − 1 , C ) 放置第 n n n 个物品,此时总价值为 v n + F ( n − 1 , C − w n ) v_n+F(n-1,C-w_n) v n ​ + F ( n − 1 , C − w n ​ ) 两种选择中总价值最大的方案就是我们的最终方案,递推式(有时也称之为状态转移方程)如下 F

0-1背包问题分析及代码实现

拈花ヽ惹草 提交于 2019-12-08 11:30:59
感觉文章开头需要说明哈为啥子要写这个文章,没错就是又被笔试给虐了,做完爱奇艺的笔试,体会最深的一句话就是出来混总是要还的,还记得研一的时候,算法老师在讲台上讲的口干舌燥,我在台下手机刷的飞快,还记得算法老师说这道题可能会考,还记得算法只考了60+(捂脸),别说都大学了,成绩能够及格就万岁,等你找工作上传成绩单时,就等着肠子悔青吧,哦对了,评审学业奖金的时候肠子也会悔青(我的8000块啊(大哭以及歇斯底里状))。 好了废话少说,先上几个链接 [ http://www.cnblogs.com/daoluanxiaozi/archive/2012/05/06/2486105.html] [ http://jingyan.baidu.com/article/3ea51489fbdaa152e61bba38.html] [ http://blog.sina.com.cn/s/blog_8cf6e8d90100zldn.html] 这几个链接都分析的不错 对于背包问题,总的来时就是,将包的容量化小,将物体个数化少,然后再逐渐增大,先解决局部的问题,然后扩大到整体局部。 #include<iostream> using namespace std ; int ZeroOneBackPack( int *Weight, int *Value, int **total, int n, int v)

动态规划—0-1背包问题(最易理解的讲解)

断了今生、忘了曾经 提交于 2019-12-08 11:29:59
0 -1 背包问题是最广为人知的动态规划问题之一,拥有很多变形。尽管在理解之后并不难写出程序,但初学者往往需要较多的时间才能掌握它。小编写这篇文章力争做到用通俗易懂的语言,最少的公式把 0-1 背包问题讲解透彻。 喜欢的小朋友,请与我多多交流哦 ~~~~ 请允许我从一则故事说起………… 话说 Lucy 带着她的亲友团去沙漠寻求宝藏,经过几天几夜的长途跋涉,终于在沙漠的那一边发现了一堆个大无比、闪闪发光的钻石,一共有 n 个。可惜的是他们身上只有一个能装钻石的背包,背包的容量为 W 。 Lucy 兴奋之余,在一堆钻石中挑出突出的钻石编号排列: 0,1,2,3 ……, n-1 。第 i 个宝石对应的体积和价值分别为 w[i] 和 v[i] 。排好后 Lucy 开始思考,和向他的亲友团求助:背包总共只能装下体积为 W 的东西,那我要装下哪些钻石才能使我们获得最大的利益呢? “很简单,用动态规划呀,那样我们就能获得最大的利益了” Bill 斩钉截铁的回答,他边说着边用木棍在沙漠上笔画着。 PS : 以上故事情节纯属虚构,若有模仿者,小编概不负责哦!请读者细细听下文讲解。 说时迟那时快, Bill 将挑出的 5 个钻石编号钻石,假设背包的容量范围在 [0,17] ,问题示例 物品的价值和重量如下表 现在 Bill 考考读者 , 通过可放和不可放表,是不是就能罗列出在背包容量值固定

背包问题java 代码

╄→гoц情女王★ 提交于 2019-12-08 11:29:50
<span style="font-family:SimSun;">背包问题,http://www.cnblogs.com/sdjl/articles/1274312.html 这篇文章介绍很详细,参照它的思路写了0/1背包问题代码。</span> package niukewang_jianzhiOffer; /** * Created by zhangwenjie05 on 16/9/10. */ public class PakageQuestion { //物体的重 static int weight[] = {2, 3, 1, 4, 6, 5}; //物体的价值 static int value[] = {5, 6, 5, 1, 19, 7}; // maxValue[i][j]保存容量为I的背包从j个物体中选择最大价值的物体放入后最大的价值和 static int maxValue[][] = new int[11][6]; public static void main(String args[]) { // 初始化 -1表示没有存储值 for (int i = 0; i < 11; i++) for (int j = 0; j < 6; j++) { maxValue[i][j] = -1; } //包容量10,有5个物体的最大价值 int r = maxValue

动态规划之完全背包问题(java实现)

雨燕双飞 提交于 2019-12-08 11:26:17
之前写了01背包问题,现在写完全背包问题。和01背包不同的是,完全背包不限定某种物品的件数,可以装0,1,2,...,而01背包只有装与不装的区别。但是思考问题的方式还是一样的,我就其中的最大值。详细代码和注释见下面代码。 package backpack; /* f[i][v]:前i件物品放入背包容量为v的背包获得的最大收益 f[i][v] = max(f[i - 1][v],f[i - 1][v - k * Wi] + k * Vi,其中 1<=k<= v/Wi) 边界条件 f[0][v] = 0; f[i][0] = 0; */ public class CompleteBackpack { private static final int N = 3; private static final int V = 5; private int weight[] = {0,3,2,2}; private int Value[] = {0,5,10,20}; private int f[][]=new int[N+1][V+1]; public int Completeknapsack() { //边界条件,第0行和第0列的值设为0 for (int i = 0;i <= N;i++){ f[i][0] = 0; } for (int v = 0;v <= V;v++){ f[0]

AcWing 11. 背包问题求方案数

妖精的绣舞 提交于 2019-12-08 01:59:24
//g[i,j]表示f[i,j]取最大值的方案数目 //体积最多是j 全部为0,v>=0 //体积恰好为j f[0][0]=0,f[i]=无穷,v>=0 //体积至少是j f[0][0]=0,f[i]=无穷,体积为负数时于0取大 #include <cstring> #include <iostream> using namespace std; const int N = 1010, mod = 1e9 + 7; int n, m; int f[N], g[N]; int main() { cin >> n >> m; memset(f, -0x3f, sizeof f);//恰好,所以负无穷 f[0] = 0; g[0] = 1; for (int i = 0; i < n; i ++ ) { int v, w; cin >> v >> w; for (int j = m; j >= v; j -- ) { int maxv = max(f[j], f[j - v] + w);//先求最大值 int cnt = 0; if (f[j] == maxv) cnt += g[j];//记录方案数目 if (f[j - v] + w == maxv) cnt += g[j-v]; g[j] = cnt % mod; f[j] = maxv; } } int res = 0;/

AcWing 10. 有依赖的背包问题

|▌冷眼眸甩不掉的悲伤 提交于 2019-12-08 01:32:26
#include <cstring> #include <iostream> #include <algorithm> using namespace std; const int N = 110; int n, m; int v[N], w[N]; int h[N], e[N], ne[N], idx; int f[N][N]; //f[i,j]表示所有从以i为根的子树中选,且总体积不超过j的方案 void add(int a, int b) { e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ; } void dfs(int u) { for(int i=h[u]; ~i; i=ne[i]) {//遍历u号点的所有子树 物品组 int son=e[i]; dfs(e[i]); //分组背包 for(int j=m-v[u]; j>=0; j--)//体积 for(int k=0; k<=j; k++)//循环决策,选哪个 当前用多少体积 //按体积划分 f[u][j]=max(f[u][j],f[u][j-k]+f[son][k]); } //把点u加进去 for (int i = m; i >= v[u]; i -- ) f[u][i] = f[u][i - v[u]] + w[u]; //清空剩余的部分 放不进去的情况 for (int