背包问题

AcWing 12. 背包问题求具体方案

亡梦爱人 提交于 2019-12-06 15:34:12
//f[i][j]=max(f[i-1][j],f[i-1][j-v[i]]+w[i]) #include <iostream> using namespace std; const int N = 1010; int n, m; int v[N], w[N]; int f[N][N]; int main() { cin >> n >> m; for (int i = 1; i <= n; i ++ ) cin >> v[i] >> w[i]; for (int i = n; i >= 1; i -- )//最小字典序,从前往后推,那么做dp的时候,从后往前 for (int j = 0; j <= m; j ++ ) {//由于状态是两维的,所以循环顺序无所谓 f[i][j] = f[i + 1][j]; if (j >= v[i]) f[i][j] = max(f[i][j], f[i + 1][j - v[i]] + w[i]); } //f[1][m]是最大价值 int j = m; for (int i = 1; i <= n; i ++ )//依次看每个物品能不能选 //保证后面大于等于0 if (j >= v[i] && f[i][j] == f[i + 1][j - v[i]] + w[i]) {//只要可以选,就必选 cout << i << ' '; j -=

三种背包模板

狂风中的少年 提交于 2019-12-06 14:17:18
零一背包倒着搜,完全背包正着搜,多重背包二进制存转化成01背包。 0-1背包 对于每种物品只有取与不取两个选择。 洛谷p1048 //https://www.luogu.com.cn/problem/P1048 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define ll long long const int maxn = 205; int cost[maxn]; int val[maxn]; int dp[105][maxn]; //dp[i][j] 当背包容积为j时,放入i的物品所获得的最大价值 int main() { int t,m; scanf("%d%d",&t,&m); for(int i=1;i<=m;i++) { scanf("%d%d",&cost[i],&val[i]); } for(int i=0;i<m;i++) dp[0][i]=0; for(int i=1;i<=m;i++) for(int j=t;j>=0;j--) { if(j>=cost[i]) //背包容积可以放下当前物品 dp[i][j]=max(dp[i-1][j],dp[i-1][j-cost[i]]+val[i]); else

开始写游戏 --- 第十篇

懵懂的女人 提交于 2019-12-06 08:31:27
开始写游戏 --- 第十篇   今天主要写了这些东西:        昨天残留了一个问题,就是 背包装备 -> 穿戴 -> 背包穿戴的装备 没有消失的问题。   那么这里就是解决穿戴装备后,让穿戴的装备消失的代码修改差异:     顺便也优化了一些代码书写。        但是又 碰到一个问题 背包 -> 穿戴装备 -> 装备栏中被换下的装备 -> 被换下的装备加入背包 -> 被换下的装备无法弹出菜单 的问题:        原因有几个:     1、加入的装备类型不一致     2、场景类 逻辑代码顺序错误   解决的方案:     1、加入的装备类型不一致       加入的装备类型不一致,主要是之前写背包的 添加功能 时,使用的类是 ItemInfo的拷贝方法,用的是 new Iteminfo 来产生一个新的 对象。       而现在有了装备类 Equip ,那就有冲突了。之前的拷贝方法不能适用。       最后是通过反射,配合 字符串生成对象 的方式解决了。       TS通过 字符串 生成 对象,网上查了好几个了,最后是找到了更好的方案。             2、场景类 逻辑代码顺序错误     至于这个问题,是由于我个人的失误,写代码多了,脑子有点乱导致的。          图里的逻辑是正确的,之前我把这两句代码的顺序弄反了。。。      之前我写的逻辑是

leetcode 322

那年仲夏 提交于 2019-12-06 06:16:23
燎天一剑 7 个月前 这道题类似于完全背包问题,每个物品都可以无限使用,但是要求背包必须装满,而且要求背包中的物品数目最少, 归纳为数学问题就是, v[i]:代表每种硬币的价值 x[i]:代表每种硬币拿的个数,0<=x[i]<=amount/v[i] 所求问题可以归纳为: 在满足:amount=v1x1+v2x2+v3x3+...+vnxn 的条件下 求: target=min{x1+x2+x3+....xn} 最简单的一种思路就是把所有{xi}的组合全部拿出来,然后让target最小即可,利用递归就可以解决问题,但是时间复杂度会很高,但是如果有好的剪枝策略,也可以使用 另外一种方法就是常规的动态规划,利用一个amout+1长度的dp数组,记录每一个状态的最优解,过程见程序和注释 public int coinChange( int [] coins, int amount) { if (coins.length == 0 ) return -1 ; //声明一个amount+1长度的数组dp,代表各个价值的钱包,第0个钱包可以容纳的总价值为0,其它全部初始化为无穷大 //dp[j]代表当钱包的总价值为j时,所需要的最少硬币的个数 int [] dp = new int [amount+ 1 ]; Arrays.fill(dp, 1 ,dp.length,Integer.MAX

洛谷——动态规划的背包问题P1060

血红的双手。 提交于 2019-12-06 04:17:40
2019-11-30 10:08:41 #include<bits/stdc++.h> #include <stdlib.h> #include <stdio.h> using namespace std; int w[30],v[30],f[50000]; int n,m; int main(){ cin>>m>>n; for(int i=1;i<=n;++i){ cin>>v[i]>>w[i]; w[i] *= v[i]; } //01背包 for(int i=1;i<=n;++i){ for(int j=m;j>=v[i];j--){ if(j>=v[i]){ f[j] = max(f[j],f[j-v[i]]+w[i]); } } } cout<<f[m]<<endl; system("pause"); return 0; } 来源: https://www.cnblogs.com/JasonPeng1/p/11961475.html

动态规划

白昼怎懂夜的黑 提交于 2019-12-06 03:44:47
 这个思路来源于搞了动态规划几十年(也算是理论奠基人之一了)的Dimitri Bertsekas,他所称之为Abstract Dynamic Programming Models。动态规划是一种在数学、计算机科学和经济学中使用的,通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。 动态规划常常适用于有重叠子问题和最优子结构性质的问题,动态规划方法所耗时间往往远少于朴素解法。 动态规划背后的基本思想非常简单。大致上,若要解一个给定问题,我们需要解其不同部分(即子问题),再合并子问题的解以得出原问题的解。通常许多子问题非常相似,为此动态规划法试图仅仅解决每个子问题一次,从而减少计算量:一旦某个给定子问题的解已经算出,则将其记忆化存储,以便下次需要同一个子问题解之时直接查表。这种做法在重复子问题的数目关于输入的规模呈指数增长时特别有用。 动态规划问题满足三大重要性质 一、抽象模型 ¶ 定义:两个集合 S,A ;策略映射 mu ;两个算子 T_mu,T 本节我们定义为了准确描述动态规划模型必不可少的5个符号。 考虑 S 和 A 为两个集合,前者我们认为是包含所有状态(state)的集合,后者我们认为是包含所有控制(control,或者action)的集合。对任意 sin S ,定义 A(s)subset A 为针对状态 s 的可行控制集。然后我们再对任意 sin S

开始写游戏 --- 第五篇

妖精的绣舞 提交于 2019-12-05 20:42:29
开始写游戏 --- 第五篇   今天写了一个这个组件:          代码:            用的时候这么用:                 这是组件的运行效果:        写是写好了。。。但是我发现,之前写好的背包出问题了。。。。。。。   购买物品的时候,物品添加到背包里。   如果购买的物品超过背包的容量怎么办?背包完全没有写检测的方法。。。   而且这个方法感觉很复杂,我想了半天了。。。。。   现在是这样子:        可见购买物品明明都超出了背包的格子了,但是背包一点反应都没有。   明天再写吧。。。。。。。      洗澡去先。 来源: https://www.cnblogs.com/dmc-nero/p/11946133.html

背包问题总结

早过忘川 提交于 2019-12-05 15:15:28
背包问题是一个np问题: 一般题意为:   存在n件物品,每件物品的重量为w[i],价值为v[i],现在有一个包,承重限制为weight,现在让你从n件物品中,选择一些物品装入背包中,在不超重的前提下,使得背包中所装物品的总价值最大。   由于每件物品【应该是每种物品】存在着两种情况,一种是,每种物品唯有一件,这种情况称为0-1背包问题;   另一种是,每种物品有无数件,这种情况称为完全背包问题。      0-1背包问题:     0-1背包问题存在两种情况,即,对于第i种物品,你只有选择或者不选择两种情况。   (1)使用动态规划来解答:           考虑对第i件物品的选择策略,有两种策略:       ①不放第i件物品,那么问题转化为前i-1件物品恰好装入容量为weight的背包中所能获得的最大价值,也即dp[i-1][weight]。【也就是整个背包重量用来装前i-1件物品】       ②放第i件物品,那么问题转化为前i-1件物品恰好装入容量为weight-w[i]的背包中所能获得的最大价值,也即dp[i-1][weight-w[i]]+c[i]。【也就是前i-1件物品只能装到重量的v-w[i]】       即选择物品和不选择物品这两种情况而已【weight为当前剩余的背包体积】       状态转移方程:         dp[i][u] = max{dp[i

【题解】完全背包问题

混江龙づ霸主 提交于 2019-12-05 14:23:41
题目描述 设有n种物品,每种物品有一个重量及一个价值。但每种物品的数量是无限的,同时有一个背包,最大载重量为m,今从n种物品中选取若干件(同一种物品可以多次选取),使其重量的和小于等于m,而价值的和为最大。 输入输出格式 输入格式: 第一行,两个整数,m(背包容量,m≤200)和n(物品数量,n≤30); 第二至第n+1行,每行两个整数wi,ci,表示每个物品的重量和价值。 输出格式: 仅一行,一个数,表示最大总价值。 输入输出样例 输入样例: 10 4 2 1 3 3 4 5 7 9 输出样例: max=12 这道题是标准的完全背包模板 因为有装或不装两种选择,所以推出动态转移方程 dp[j]=max(dp[j],dp[j-w[i]]+v[i]); 注意! 因为每个物品可以装无限个,装完之后还能再装,以前装过的物品也可以对动态转移方程造成影响,与01背包不同,所以DP顺序是从前往后推。 代码: #include<iostream> using namespace std; int m,n,w[35],v[35]; int dp[205]; int main() { cin>>m>>n; for(register int i=1;i<=n;++i) cin>>w[i]>>v[i]; for(register int i=1;i<=n;++i) { for(register int

背包问题总结

六眼飞鱼酱① 提交于 2019-12-05 13:11:46
1.背景: 1.1 什么是背包问题:背包问题指这样一类问题,题意往往可以抽象成:给定一组物品,每种物品都有自己的重量和价格,在限定的总重量内,我们如何选择,才能使得物品的总价格最高。(来自百度百科) 1.2 背包问题的种类:就ACM或者其它算法竞赛而言,背包问题可以分为8种类型,其中最基础的是0/1背包问题。作为动态规划的典型问题,其状态转移方程往往需要认真理解并能自行推出。这八种问题分别为:0/1背包问题、完全背包问题、多重背包问题、混合三种背包问题、二维费用背包问题、分组背包问题、有依赖的背包问题、求背包问题的方案总数。 2.0/1背包问题 2.1 问题描述:有N件物品和一个容量为V的背包。第i件物品的费用(即体积,下同)是w[i],价值是val[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。 2.2 解题思路:用动态规划的思路,阶段就是“物品的件数”,状态就是“背包剩下的容量”,那么很显然f [ i , v ] 就设为从前 i 件物品中选择放入容量为 v 的背包最大的价值。那么状态转移方程为: f[i][v]=max{ f[i-1][v],f[i-1][v-w[i]]+val[i] }。 这个方程可以如下解释:只考虑子问题“将前 i 个物品放入容量为 v 的背包中的最大价值”那么考虑如果不放入 i ,最大价值就和 i 无关,就是 f[ i