Given a set of n items, each with a weight w[i] and a value v[i], determine a way to choose the items into a knapsack so that the total weight is less than or equal to a given limit B and the total value is as large as possible. Find the maximum total value. (Note that each item can be only chosen once).

Input

The first line contains the integer T indicating to the number of test cases.

For each test case, the first line contains the integers n and B.

Following n lines provide the information of each item.

The i-th line contains the weight w[i] and the value v[i] of the i-th item respectively.

1 <= number of test cases <= 100

1 <= n <= 500

1 <= B, w[i] <= 1000000000

1 <= v[1]+v[2]+...+v[n] <= 5000

All the inputs are integers.

Output

For each test case, output the maximum value.

Sample Input

1
5 15
12 4
2 2
1 1
4 10
1 2

Sample Output

15

自己找了两个背包的代码敲了上去,第一个因为重复查找的次数太多TEL, 第二个因为数组空间开的太大爆了。

TEL代码

 1 int n, W;
2 int w[MAX_N], v[MAX_N];
3
4 int rec(int i, int j) {
5 int res;
6 if (i == n) {
7 res = 0;
8 } else if (j < w[i]) {
9 res = rec(i + 1, j);
10 } else {
11 res = max(rec(i + 1, j), rec(i + 1, j - w[i]) + v[i]);
12 }
13 return res;
14 }
15
16 void solve() {
17 printf("%d\n", rec(0, W));
18 }

上面的代码可以优化,试产殉国的位置不再进行查询,但是要开一的dp[MAX_N][MAX_W]的数组,因为MAX_W的取值范围太大所以这种方法不能够用来解答此题。

优化代码

 1 int dp[MAX_N][MAX_W];
2
3 int rec(int i, int j) {
4 if (dp[i][j] >= 0)
5 return dp[i][j];
6
7 int res;
8 if (i == n) {
9 res = 0;
10 } else if (j < w[i]) {
11 res = rec(i+1, j);
12 } else {
13 res = max(rec(i+1, j), rec(i+1, j-w[i]) + v[i]);
14 }
15 return dp[i][j] = res;
16 }
17
18 void solve() {
19 memset(dp, -1, sizeof(dp));
20 printf("%d\n", rec(0, W));
21 }

超大背包,因为此题的背包数量太多,用超大背包的话算法复杂度是O(2^n)级别,所以此题也不能用超大别抱来解决。超大背包只适合用来解决别博爱的数量很少但是重量和价值都很大的情况。

超大背包代码:

 1 typedef long long ll;
2
3 int n;
4 ll w[MAX_N], v[MAX_N];
5 ll W;
6
7 pair<ll, ll> ps[1 << (MAX_N / 2)];
8
9 void solve() {
10 int n2 = n / 2;
11 for (int i = 0; i < 1 << n2; i++) {
12 ll sw = 0, sv = 0;
13 for (int j = 0; j < n2; j++) {
14 if (i >> j & 1) {
15 sw += w[j];
16 sv += v[j];
17 }
18 }
19 ps[i] = make_pair(sw, sv);
20 }
21
22 sort(ps, ps + (1 << n2));
23 int m = 1;
24 for (int i = 1; i < 1 << n2; i++) {
25 if (ps[m-1].second < ps[i].second) {
26 ps[m++] = ps[i];
27 }
28 }
29
30 ll res = 0;
31 for (int i = 0; i < 1 << (n-n2); i++) {
32 ll sw = 0, sv = 0;
33 for (int j = 0; j < n - n2; j++) {
34 if (i >> j & 1) {
35 sw += w[n2+j];
36 sv += v[n2+j];
37 }
38 }
39 if (sw <= W) {
40 ll tv = (lower_bound(ps, ps+m, make_pair(W - sw, INF)) - 1) -> second;
41 res = max(res, sv + tv);
42 }
43 }
44 printf("%d\n", res);
45 }

题解:

最大质量为1000000000,数组肯定不够用。

不过,总价值才5000,我们以价值为轴开辟记录剩余可载质量的一维数组,后面的做法就与01背包如出一辙。

AC代码

 1 #include<cstdio>
2 #include<cstring>
3 int main(){
4 int weight[5001], t, i, j, n, B, max_value, w, v;
5 scanf("%d", &t);
6
7 while (t--){
8 scanf("%d%d", &n, &B);
9 memset(weight, 0, sizeof(weight));
10 weight[0] = B, max_value = 0;
11
12 for (j = 0; j < n; ++j){
13 scanf("%d%d", &w, &v);
14 for (i = max_value; i >= 0; --i){
15 if (weight[i] - w > weight[i + v]) weight[i + v] = weight[i] - w;
16 }
17 for (i = max_value + 1; i <= 5000; ++i) if (weight[i]) max_value = i;
18 }
19
20 printf("%d\n", max_value);
21 }
22 return 0;
23 }

总结:通过这题也让我明白了自己对摸板代码的理解程度还远远不够,所以才会出现这样的情况。

加油!!!!!!!!!!

B - 真·签到题 FZU - 2214(背包)的更多相关文章

  1. D - 下个也是签到题 FZU - 2221(博弈)

    ZB loves watching RunningMan! There's a game in RunningMan called 100 vs 100. There are two teams, e ...

  2. HDU 6312.Game-博弈-签到题 (2018 Multi-University Training Contest 2 1004)

    2018 Multi-University Training Contest 2 6312.Game 博弈,直接官方题解,懒了. 考虑将游戏变成初始时只有2~n,如果先手必胜的话,那么先手第一步按这样 ...

  3. FZU 2214 Knapsack problem(背包问题)

    Description 题目描述 Given a set of n items, each with a weight w[i] and a value v[i], determine a way t ...

  4. A 洛谷 P3601 签到题 [欧拉函数 质因子分解]

    题目背景 这是一道签到题! 建议做题之前仔细阅读数据范围! 题目描述 我们定义一个函数:qiandao(x)为小于等于x的数中与x不互质的数的个数. 这题作为签到题,给出l和r,要求求. 输入输出格式 ...

  5. fjwc2019 D3T1 签到题 (贪心)

    #184. 「2019冬令营提高组」签到题 每次询问接近O(1).......考虑贪心 怎么贪心呢? 对于相邻的两个数,我们要保证异或x后单调不降 我们找到两个数二进制上最高的相异位 当左边的数相异位 ...

  6. CTF-练习平台-WEB之 签到题

    一.签到题 根据提示直接加群在群公告里就能找到~

  7. 洛谷P3601签到题(欧拉函数)

    题目背景 这是一道签到题! 建议做题之前仔细阅读数据范围! 题目描述 我们定义一个函数:qiandao(x)为小于等于x的数中与x不互质的数的个数. 这题作为签到题,给出l和r,要求求. 输入输出格式 ...

  8. 【洛谷九月月赛T1】签到题(bsgs)(快速乘)

    说好的签到题呢qwq....怎么我签到题都不会啊qwq 之后看了bsgs才发现貌似不是那么那么难fake!!什么东西... 先贴上部分分做法(也就是枚举1的个数,然后每一步都进行取模(这和最后取模结果 ...

  9. WEB新手之签到题

    写一写web新手赛的题. 这是签到题,开始时需要耐心等待页面中字母全部出现. 字母全部出现后,会跳转到另一个界面,如上图所示.F12没什么特别的地方,这题应该有点难度. 按往常一样,先抓包. 按英文提 ...

随机推荐

  1. Pandas初体验

    目录 Pandas 一.简介 1.安装 2.引用方法 二.series 1.创建方法 2.缺失数据处理 2.1 什么是缺失值 2.2 NaN特性 2.3 填充NaN 2.4 删除NaN 2.5 其他方 ...

  2. HBase 数据存储结构

    在HBase中, 从逻辑上来讲数据大概就长这样: 单从图中的逻辑模型来看, HBase 和 MySQL 的区别就是: 将不同的列归属与同一个列族下 支持多版本数据 这看着感觉也没有那么太大的区别呀, ...

  3. sqlyog如何增删改查?

    转: sqlyog如何增删改查? 下面是一道完整的 sqlyog 增删改查的练习, 顺着做下去,可以迅速掌握. 1. 创建部门表dept,并插入数据: 2. 创建emp员工表,并插入数据: sql 代 ...

  4. apicloud编译所需的ios证书的获取方法

    在我们通过apicloud或hbuilderX这些工具打包ios应用的时候,需要一个ios证书. 那么我们如何生成这个ios证书呢?网上介绍的方法都是需要使用mac电脑,然后用mac电脑的钥匙串访问的 ...

  5. CCF(消息传递口:80分):字符串相关+队列

    消息传递口 201903-4 本题主要是利用队列进行模拟,因为一开始我没有注意到要按照顺序,所以一开始的解法错误. #include<iostream> #include<algor ...

  6. CVE-2016-10033 WordPress <= 4.6 命令执行漏洞

    漏洞参考 https://www.jianshu.com/p/85ac4af9f947 漏洞信息 这个锅还是要PHPMailer背(CVE-2016-10033,WordPress 使用 PHPMai ...

  7. 记录 Allsec 解题过程

    开局打开URL:http://119.3.191.245:65532/#/allsecPlayGame,前去做游戏 游戏URL:http://119.3.191.245:8877/Login.php ...

  8. 再探命令行传参之c与python

    继上一次java命令行传参 python sys模块包括了一组非常实用的服务,内含很多函数方法和变量,用来处理Python运行时配置以及资源,从而可以与前当程序之外的系统环境交互,如:python解释 ...

  9. Java并发编程之锁机制

    锁分类 悲观锁与乐观锁 悲观锁认为对于同一个数据的并发操作,一定是会发生修改的,哪怕没有修改,也会认为修改.因此对于同一个数据的并发操作,悲观锁采取加锁的形式.悲观的认为,不加锁的并发操作一定会出问题 ...

  10. Python基础之数据类型详解

    为什么会有数据类型? 在介绍具体的数据类型之前,需要了解为什么需要区分数据类型.我们知道,一个公司会有很多个大的部门,每个部门下又会有许多细分的小部门,构成了公司的完整体系结构.如果把python的数 ...