背包问题

分组背包问题

狂风中的少年 提交于 2020-01-20 19:45:33
分组背包问题:已知一个体积为m的背包,共有n种物品,每一种物品有s个,每个的体积v和权值w不一定相同,要求从每一种物品中选某件物品,使得在总体积不超过m的情况下,所选的总权值最大。 代码如下(已优化成一维滚动数组) #include <iostream> #include <algorithm> #define N 110 using namespace std; int n, m; int s[N], v[N][N], w[N][N]; int f[N]; int main() { cin >> n >> m; for (int i = 1; i <= n; i++) { cin >> s[i]; for (int j = 1; j <= s[i]; j++) { cin >> v[i][j] >> w[i][j]; } } for (int i = 1; i <= n; i++) // 枚举所有种类 for (int j = m; j >= 0; j--) // 枚举所有体积 for (int k = 1; k <= s[i]; k++ ) // 枚举所有选项 if(v[i][k] <= j) // 只有在这个条件下,需要进行状态转移 f[j] = max (f[j], f[j - v[i][k]] + w[i][k]); cout << f[m] << endl;

offer(背包问题、DP)

自作多情 提交于 2020-01-20 18:11:07
蒜头君很早就想出国,现在他已经考完了所有需要的考试,准备了所有要准备的材料,于是,便需要去申请学校了。要申请国外的任何大学,你都要交纳一定的申请费用,这可是很惊人的。蒜头君没有多少钱,总共只攒了n万元。他将在m个学校中选择若干的(当然要在他的经济承受范围内)。每个学校都有不同的申请费用a (万美元),并且蒜头君估计了他得到这个学校offer的可能性b。 不同学校之间是否得到offer不会互相影响。"I NEED A OFFER",他大叫一声。帮帮这个可怜的人吧,帮助他计算一下,他可以收到至少一份offer的最大概率。 (如果蒜头君选择了多个学校,得到任意一个学校的offer都可以)。 输入格式 第一行有两个正整数n,m(0≤n≤10000,0≤m≤10000)。 后面的m行,每行都有两个数据a i (整型), b i (实型)分别表示第i个学校的申请费用和可能拿到offer的概率。 输出格式 每组数据都对应一个输出,表示蒜头君可能得到至少一份offer的最大概率。百分数表示,精确到小数后一位。 样例输入 10 3 4 0.1 4 0.2 5 0.3 样例输出 44.0% 01背包问题 这里我们的状态转移方程会和前面的01背包的状态转移方程发生变化。 dp[j]表示花费j元,至少可以拿到一个学校的offer的概率。 当有一所学校是花费x元拿到offer的概率是y。所以这个时候就是1

背包问题整理

我的未来我决定 提交于 2020-01-18 16:06:58
背包问题 给定一组物品,每种物品都有自己的重量和价值,现有一个背包,能承受的重量有限,在受限制的重量下,取若干物品,使得总价值最大。这一类问题,被称为背包问题。 01背包(物品个数为1) for (int i = 1; i <= N; ++i) { for (int j = 0; j <= V; ++j) { if(j >= c[i]) { dp[i][j] = max(dp[i - 1][j - c[i]] + w[i], dp[i - 1][j]); } else { dp[i][j] = dp[i - 1][j]; } } } 时间上是两重循环,时间复杂度为O(NV)。空间是二维的,空间复杂度也为O(NV)。 for (int i = 1; i <= n; ++i) for (int j = v; j >= c[i]; --j) { dp[j] = max(dp[j - c[i]] + w[i], dp[j]); } 这个做法空间复杂度也为O(V)。 多重背包(物品个数有限) for (int i = 1; i <= N; i++) { for (int j = 0; j <= V; j++) { for (int k = 0; k <= n[i]; k++) { if (j >= c[i] * k) { dp[i][j] = max(dp[i - 1][j - c[i] *

并不优雅的背包算法

白昼怎懂夜的黑 提交于 2020-01-18 15:41:40
问题描述:有若干物品,物品的质量和体积已知。有一个容积固定的背包,怎样在背包中装入质量尽可能大的物品 代码如下,注释应该足够详细,只是代码风格不太优雅(捂脸) #include<iostream> #include<vector> using namespace std; //用来定义物品,需要提供质量和体积 class BagObj { public: bool isSelected = false;//物品是否被选中 int quality = 0;//质量 int volume = 0;//体积 //传入体积和质量 BagObj(int fromVol, int fromQua); }; BagObj::BagObj(int fromVol, int fromQua) { quality = fromQua; volume = fromVol; } class BagHandle { private: int objNum = 0;//物品的总数 int bagVol = 0;//背包的体积 vector<BagObj> objList;//物品的属性列表 int bagProblemDealCore(int restVol,//剩余的背包体积 vector<BagObj>::iterator fromIter//物品开始迭代的位置 ); public: /

洛谷·付公主的背包

安稳与你 提交于 2020-01-18 08:09:01
初见安~这里是传送门: 洛谷P4389 付公主的背包 题解 30%的数据明显我们可以暴力跑背包,但是大点点就不行了。我们考虑多项式。 根据 母函数 ,我们对于每一种物品都可以写成一个多项式的形式,比如某物品大小为v,那么就有多项式: 对于n个物品,我们将他们每个的多项式都乘起来,所求就是最后那个多项式的前n项的系数。 但是这样做的复杂度是多少? ,明显过不了。所以我们可能还要优化一下公式。 对于第i个物品的多项式为: 【无穷等比数列求和 所以我们要求的就是: 全是累乘啊。我们把乘法变加法,两边同时取对。 现在看起来已经差不多了,那么我们的问题就是f(i)了。因为我们的物品并不是真的可以取用无限个的,所以这个式子我们还得继续展开,在合适的时候回到这个限制上。 因为有: 所以我们把f(i)带进去:【这里是求 ,直接用 代替 了。这一步求导+积分可以手推一下,下面是个平方项的,后来约掉了 里面好像有个 ,所以我们是时候展开了:【最后这一步积分的还原式手推也会有点点吃力QuQ套求导公式吧。加油 至此,就是 了。因为回到上面,我们括号里面是 求和,所以n个多项式对应的系数相加即可,最后exp回来就是所求了。 【 感觉这个题就是在考你数学的导数变换啊……恐怖。 】 上代码—— #include<algorithm>//princes Fu #include<iostream> #include

彻底理解0-1背包问题

生来就可爱ヽ(ⅴ<●) 提交于 2020-01-18 05:40:07
0-1背包问题概念 背包问题本质是个求最优解的问题: 有个背包有V大小的空间可以存放物品,现在有n个物品,每个物品体积分别为v1、v2...、vn,价值分别为w1、w2...、wn。现在求解: 如何使物品尽可能多的放在背包中,使得背包中的物品总价值最大? 0-1背包问题指的是每个物品只能使用一次 解决这类问题,大致有2类方法: 递归算法、动态规划算法 ,下面详细讲解3种算法(借鉴了 博主的论文 )。 一、递归算法 递归算法解决这类问题大致的核心思想: 我们用B[k][C]表示前k个物品放进容量为C的背包里,得到的最大的价值。 我们用自顶向下的角度来看,假如我们已经进行到了最后一步(即求解将k个物品放到背包里获得的最大价值),此时我们便有两种选择: 1、不放第k个物品,此时总价值为B[k−1][C] 2、放置第k个物品,此时总价值为wk+B[k−1][C−vk] 两种选择中总价值最大的方案就是我们的最终方案,递推式(有时也称之为状态转移方程)如下 B[k][C]=max(B[k-1][C],wk+B[k−1][C−wk]) 编程如下: public class test { //物品总量,最大承重 static int N = 6; static int W = 21; static int[][] B = new int[N][W]; static String[][] B_ =

背包问题

*爱你&永不变心* 提交于 2020-01-15 16:25:37
1. 0 1 背包问题: 1 #pragma GCC optimize("Ofast") 2 #include <iostream> 3 #include <algorithm> 4 #define Maxsize 100 + 1 5 using namespace std; 6 typedef long long ll; 7 struct node{ 8 int v; 9 int w; 10 }; 11 node arr[Maxsize]; 12 ll dp[Maxsize][10000 + 1]; 13 int main(){ 14 ios :: sync_with_stdio(false); 15 cin.tie(0); cout.tie(0); 16 int n,capa; 17 cin >> n >> capa; 18 for(int i = 1; i <= n; i++) 19 cin >> arr[i].w >> arr[i].v; 20 21 for(int i = 1; i <= n; i++){ 22 for(int j = 1; j <= capa; j++){ 23 if(arr[i].w <= j)dp[i][j] = max(dp[i-1][j],dp[i-1][j-arr[i].w] + arr[i].v); 24 else dp[i][j] = dp

完全背包

淺唱寂寞╮ 提交于 2020-01-13 18:52:09
什么是完全背包 完全背包,就是在背包容量有限的情况下,每件物品可以选无数多件。 如何求解完全背包 完全背包和01背包一样,拥有最优子结构。所以也可以用动态规划来解。 还是先确定动态转移方程,把01背包的转移方程进行发展,可以得到 f(n,m)=max{f(n-1,m-k×w[n] )+k×v[n] │ 0≤k×w[n]≤M} K表示选k件n类物品。其实01背包也可以用这个递推式来解的,只是k非0即1。 优化动态转移矩阵 如何优化这个转移矩阵呢?我们先回顾一下01背包是怎么优化的?我们把二维矩阵优化成一维数组,但是在计算时m要逆序。为怎么呢?因为第n件物品是不能复选的。 那我们在来看看如果m不逆序会发生什么? 我先们来看看“上次计算的结果”是什么呢?“上次计算的结果”无非是两种情况 f[n-2][m] 或者是 f[n-2][m-w[n-1] ]+v[n-1] 先考虑 第二种情况叠加 的情况,就会发现。。。我们根本没法叠加。但是如果我们把转移式改成 f[n][m]=max{f[n-1][m],f[n][m-w[n]]+v[n]} 就可以叠加了(就是后面那个n不减了)。结果发现这和 f(n,m)=max⁡{f(n-1,m-2×w[n] )+2×v[n]} 是等价的。那不就正好达到了取2件i物品的目的吗。在这样叠加上去,就和取k件i物品就等价了。这时候你可能会产生这样一个问题

POJ3181 Dollar Dayz 动态规划 背包解法 解题报告

陌路散爱 提交于 2020-01-13 13:23:01
题目链接: http://acm.pku.edu.cn/JudgeOnline/problem?id=3181 题目大意: 输入n,和k,问将n用1到k这k个数字进行拆分,有多少种拆分方法。例如: n=5,k=3 则有n=3+2,n=3+1+1,n=2+1+1+1,n=2+2+1,n=1+1+1+1+1这5种拆分方法 解题思路: 这个题目是个比较明显的动态规划,如果想不到是背包问题,也可以写出状态转移方程如下: 用a[i][j]表示考虑到用数j进行拼接时数字i的拼接方法,可以得到状态转移方程如下: a[i][j]=a[i][j-1]+a[i-j][j-1]+a[i-2j][j-1]+a[i-3j][j-1]…+a[0][j-1]意思很明显,就将j-1状态可以到达a[i][j]的状态的数字相加。由于得到的结果可能相当大,已经超过了long long,所以应该用大数。但是若跑完所有数据,用大数会超过一秒,我们通过大数的程序可以达到,最大的数字为33位,那么,我们可以将两个long long的数字进行拼接,组成一个超过33位的数。这样增加了速度,这种比较慢的算法也可以不超时。ac的代码如下: #include <iostream> #include<cstdio> using namespace std; long long a[1200][200]={0},b[1200][120]=

acwing 10. 有依赖的背包问题

放肆的年华 提交于 2020-01-12 02:24:21
传送门 有 N 个物品和一个容量是 V 的背包。 物品之间具有依赖关系,且依赖关系组成一棵树的形状。如果选择一个物品,则必须选择它的父节点。 如下图所示: 如果选择物品5,则必须选择物品1和2。这是因为2是5的父节点,1是2的父节点。 每件物品的编号是 i,体积是 vi,价值是 wi,依赖的父节点编号是 pi。物品的下标范围是 1…N。 求解将哪些物品装入背包,可使物品总体积不超过背包容量,且总价值最大。 输出最大价值。 输入格式 第一行有两个整数 N,V,用空格隔开,分别表示物品个数和背包容量。 接下来有 N 行数据,每行数据表示一个物品。 第 i 行有三个整数 vi,wi,pi,用空格隔开,分别表示物品的体积、价值和依赖的物品编号。 如果 pi=−1,表示根节点。 数据保证所有物品构成一棵树。 输出格式 输出一个整数,表示最大价值。 数据范围 1≤N,V≤100 1≤vi,wi≤100 父节点编号范围: 内部结点:1≤pi≤N; 根节点 pi=−1; 输入样例 5 7 2 3 -1 2 2 1 3 5 1 4 7 2 3 6 2 输出样例: 11 对于这个我们首先找到根节点,然后遍历根节点连接的点,对于每个点递归进行同样的操作,然后对于同一个根节点的点组算一下最大值即可。 AC代码如下: #include<bits/stdc++.h> using namespace std;