01 背包 完全背包 多重背包 三件套(这三个背包 想要吗?)
2017-08-08 16:44
190 查看
这几天 正在学习 动态规划 , 背包问题更是 必须学习 的内容 ,抽象难懂的 01 背包 问题 终于在我的 不懈努力下 ,把他给 攻克占领 啦 , 哈哈哈 , 后面的 小怪 完全背包 和 多重背包 更是不在话下!下面 根据一道题 来 分析一下 。
为了挽救灾区同胞的生命,心系灾区同胞的你准备自己采购一些粮食支援灾区,现在假设你一共有资金n元,而市场有m种大米,每种大米都是袋装产品,其价格不等,并且只能整袋购买。
请问:你用有限的资金最多能采购多少公斤粮食呢?
后记:
人生是一个充满了变数的生命过程,天灾、人祸、病痛是我们生命历程中不可预知的威胁。
月有阴晴圆缺,人有旦夕祸福,未来对于我们而言是一个未知数。那么,我们要做的就应该是珍惜现在,感恩生活——
感谢父母,他们给予我们生命,抚养我们成人;
感谢老师,他们授给我们知识,教我们做人
感谢朋友,他们让我们感受到世界的温暖;
感谢对手,他们令我们不断进取、努力。
同样,我们也要感谢痛苦与艰辛带给我们的财富~
Output
对于每组测试数据,请输出能够购买大米的最多重量,你可以假设经费买不光所有的大米,并且经费你可以不用完。每个实例的输出占一行。
8 2
2 100 4
4 100 2
Sample Output
400
这道题 因为 数据的 范围都比较小 所以 多重背包 的 简单 01 方法 与 通
bef6
过二进制 优化 后的 01 背包 方法 都可 AC 。
先 简单说一下 前者 : 顾名思义 即使 完全套用 01 背包的方法 但 不同的 是 物品的数量 有多个 ,那么 也没 问题, 嘿嘿, 全部 都 便利一边不就行了 嘛, 是吧! 这里 提一下 : 01背包 的 方法中 有 用 一位数组 和 二维数组 两种 ,之所以 用后者 是因为 ,n种 物品 都只有一个 ,所以 弄了 一个 具有 n 行的 二维数组 ,每一种物品都分了 一行 , 是为了 避免 同一种物品 多次 放入 , 而 采用一位数组 是 采用 倒序 遍历 , 也是 同样的 道理 , 所以 完全背包 与 多重背包 同种 文品 有多个 就 不用采用 二维数组 啦 ,直接 用一位数组 倒序 遍历 , 比较简单 。 下面是完整代码(前一种方法)。(把第i种物品换成n[i]件01背包中的物品,则得到了物品数为∑n[i]的01背包问题,直接求解,复杂度仍然是O(V*∑n[i])。
)
看了上面的代码 之后 是不是觉得 这 太简单了把 ,是吧。我 但是 也是这么 觉得 的 但是 这 知识 动态规划 中 很简单 的 题;算是 入门题吧,所以呀 大家不要 觉得 啥都会啦 ,路还很长。
下面是 二进制 优化过的 方法 :但是我们期望将它转化为01背包问题之后能够像完全背包一样降低复杂度。仍然考虑二进制的思想,我们考虑把第i种物品换成若干件物品,使得原问题中第i种物品可取的每种策略——取0..n[i]件——均能等价于取若干件代换以后的物品。另外,取超过n[i]件的策略必不能出现。
方法是:将第i种物品分成若干件物品,其中每件物品有一个系数,这件物品的费用和价值均是原来的费用和价值乘以这个系数。使这些系数分别为 1,2,4,…,2^(k-1),n[i]-2^k+1,且k是满足n[i]-2^k+1>0的最大整数。例如,如果n[i]为13,就将这种物品分成系数分别为1,2,4,6的四件物品。
分成的这几件物品的系数和为n[i],表明不可能取多于n[i]件的第i种物品。另外这种方法也能保证对于0..n[i]间的每一个整数,均可以用若干个系数的和表示,这个证明可以分0..2^k-1和2^k..n[i]两段来分别讨论得出,并不难,希望你自己思考尝试一下。
下面是 完整代码代码:
悼念512汶川大地震遇难同胞——珍惜现在,感恩生活
急!灾区的食物依然短缺!为了挽救灾区同胞的生命,心系灾区同胞的你准备自己采购一些粮食支援灾区,现在假设你一共有资金n元,而市场有m种大米,每种大米都是袋装产品,其价格不等,并且只能整袋购买。
请问:你用有限的资金最多能采购多少公斤粮食呢?
后记:
人生是一个充满了变数的生命过程,天灾、人祸、病痛是我们生命历程中不可预知的威胁。
月有阴晴圆缺,人有旦夕祸福,未来对于我们而言是一个未知数。那么,我们要做的就应该是珍惜现在,感恩生活——
感谢父母,他们给予我们生命,抚养我们成人;
感谢老师,他们授给我们知识,教我们做人
感谢朋友,他们让我们感受到世界的温暖;
感谢对手,他们令我们不断进取、努力。
同样,我们也要感谢痛苦与艰辛带给我们的财富~
Input
输入数据首先包含一个正整数C,表示有C组测试用例,每组测试用例的第一行是两个整数n和m(1<=n<=100, 1<=m<=100),分别表示经费的金额和大米的种类,然后是m行数据,每行包含3个数p,h和c(1<=p<=20,1<=h<=200,1<=c<=20),分别表示每袋的价格、每袋的重量以及对应种类大米的袋数。Output
对于每组测试数据,请输出能够购买大米的最多重量,你可以假设经费买不光所有的大米,并且经费你可以不用完。每个实例的输出占一行。
Sample Input
18 2
2 100 4
4 100 2
Sample Output
400
这道题 因为 数据的 范围都比较小 所以 多重背包 的 简单 01 方法 与 通
bef6
过二进制 优化 后的 01 背包 方法 都可 AC 。
先 简单说一下 前者 : 顾名思义 即使 完全套用 01 背包的方法 但 不同的 是 物品的数量 有多个 ,那么 也没 问题, 嘿嘿, 全部 都 便利一边不就行了 嘛, 是吧! 这里 提一下 : 01背包 的 方法中 有 用 一位数组 和 二维数组 两种 ,之所以 用后者 是因为 ,n种 物品 都只有一个 ,所以 弄了 一个 具有 n 行的 二维数组 ,每一种物品都分了 一行 , 是为了 避免 同一种物品 多次 放入 , 而 采用一位数组 是 采用 倒序 遍历 , 也是 同样的 道理 , 所以 完全背包 与 多重背包 同种 文品 有多个 就 不用采用 二维数组 啦 ,直接 用一位数组 倒序 遍历 , 比较简单 。 下面是完整代码(前一种方法)。(把第i种物品换成n[i]件01背包中的物品,则得到了物品数为∑n[i]的01背包问题,直接求解,复杂度仍然是O(V*∑n[i])。
)
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; int dp[110]; int value[210]; int weight[100]; int num[100]; int main() { int t; cin>>t; while(t--) { int n, m; scanf("%d%d", &n, &m); for(int i = 1; i <= m; i++) scanf("%d%d%d", &weight[i], &value[i], &num[i]); memset(dp, 0, sizeof(dp)); for(int i = 1; i <= m; i++) for(int j = 1; j <= num[i]; j++) for(int k = n; k >= weight[i]; k--) dp[k] = max(dp[k], dp[k-weight[i]] + value[i]); printf("%d\n", dp ); } return 0; }
看了上面的代码 之后 是不是觉得 这 太简单了把 ,是吧。我 但是 也是这么 觉得 的 但是 这 知识 动态规划 中 很简单 的 题;算是 入门题吧,所以呀 大家不要 觉得 啥都会啦 ,路还很长。
下面是 二进制 优化过的 方法 :但是我们期望将它转化为01背包问题之后能够像完全背包一样降低复杂度。仍然考虑二进制的思想,我们考虑把第i种物品换成若干件物品,使得原问题中第i种物品可取的每种策略——取0..n[i]件——均能等价于取若干件代换以后的物品。另外,取超过n[i]件的策略必不能出现。
方法是:将第i种物品分成若干件物品,其中每件物品有一个系数,这件物品的费用和价值均是原来的费用和价值乘以这个系数。使这些系数分别为 1,2,4,…,2^(k-1),n[i]-2^k+1,且k是满足n[i]-2^k+1>0的最大整数。例如,如果n[i]为13,就将这种物品分成系数分别为1,2,4,6的四件物品。
分成的这几件物品的系数和为n[i],表明不可能取多于n[i]件的第i种物品。另外这种方法也能保证对于0..n[i]间的每一个整数,均可以用若干个系数的和表示,这个证明可以分0..2^k-1和2^k..n[i]两段来分别讨论得出,并不难,希望你自己思考尝试一下。
下面是 完整代码代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; int dp[200]; int value[200]; int weight[100]; int num[100]; int main() { int t; cin>>t; while(t--) { int n, m; scanf("%d%d", &n, &m); for(int i = 1; i <= m; i++) scanf("%d%d%d", &weight[i], &value[i], &num[i]); memset(dp, 0, sizeof(dp)); for(int i = 1; i <= m; i++) { int k = 1; while(k < num[i]) { for(int j = n; j >= k * weight[i]; j--) dp[j] = max(dp[j], dp[j - k*weight[i]] + k*value[i]); num[i] -= k; k *= 2; } for(int j = n; j >= num[i]*weight[i]; j--) dp[j] = max(dp[j], dp[j - num[i]*weight[i]] + num[i]*value[i]); } printf("%d\n", dp ); } return 0; }
相关文章推荐
- 背包之01背包、完全背包、多重背包详解
- 01背包,完全背包,多重背包详解
- 背包之01背包、完全背包、多重背包详解
- 动态规划初步( 01 背包、完全背包、多重背包)
- 01背包问题和完全背包问题
- 01背包,完全背包,多重背包 ,模板代码
- 01背包、完全背包、多重背包问题分析
- HDU 5410 CRB and His Birthday (01背包,完全背包,混合)
- 01背包,完全背包,模板
- 01背包与完全背包就差一个顺序
- 01背包,完全背包,多重背包
- 背包问题(01背包,完全背包,多重背包)
- HDU 5410 CRB and His Birthday 混合背包(01背包和完全背包混合)
- 背包问题中的01背包和完全背包
- 01背包与完全背包问题
- 背包之01背包、完全背包、多重背包详解(转)
- hdu 1059 多重背包 二进制优化 (完全 , 01)背包结婚
- hdu 5410 01+完全背包
- 背包模板(01背包,完全背包,多重背包)
- 动态规划之01背包,完全背包,分组背包