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. Vue框架- 指令操作

    目录 一.Vue指令操作 1. 表单指令 2. 条件指令 3. 循环指令 4. 斗篷指令 5. 实例成员:delimiter分隔符(了解) 6. filter过滤器 7. computed计算属性 8 ...

  2. Go的指针

    目录 指针 一.指针的声明 二.指针的默认值(Zero Value) 三.指针的解引用 四.向函数传递指针参数 1.非 数组/切片 指针传参 2.数组/切片 指针传参 五.Go不支持指针运算 指针 指 ...

  3. 生产者与消费者以及ActiveMQ

    生产者与消费者以及ActiveMQ 一. 多线程实现生产者与消费者 1.1 生产者与消费者头文件 #pragma once #include <iostream> #include < ...

  4. 后端程序员之路 59、go uiprogress

    gosuri/uiprogress: A go library to render progress bars in terminal applicationshttps://github.com/g ...

  5. 后端程序员之路 32、Index搜索引擎实现分析1-类的设计

    # 1.forward_index 正排索引(正向索引)- filter_t- filter_judge # 2.inverted_index 倒排索引(反向索引)- inverted_pre_sco ...

  6. Vue.js 多选列表(Multi-Select)组件

    搬运公众号早前文章 多选列表 (Multi-Select) 是一种将所有选项列出,并允许用户利用 Ctrl/Shift 键进行多选的 UI 元素.这是一种常见的设计元素.有时候为了节省空间,我们会将选 ...

  7. python中lambda、yield、map、filter、reduce的使用

    1. 匿名函数lambda python中允许使用lambda关键字定义一个匿名函数.所谓的匿名函数就是说使用一次或者几次之后就不再需要的函数,属于"一次性"函数. #例1:求两数 ...

  8. 《C++ Primer》笔记 第4章 表达式

    C++的表达式要不然是右值(right-value or read-value),要不然就是左值(left-value or location-value). 当一个对象被用作右值的时候,用的是对象的 ...

  9. crudapi零代码开发平台应用场景和成功案例

    应用场景 在前面文章中,已经介绍了crudapi主要功能和使用方式,本文主要介绍crudapi应用场景以及具体的使用方式. 概要 crudapi属于产品级的零代码平台,无需编程,通过配置自动生成cru ...

  10. 文件包含-phpinfo()

    我也是听朋友说有这个姿势的,github有集成好的环境 先讲一下利用phpinfo上传文件,然后在文件包含的原理: 在给PHP发送POST数据包时,如果数据包里包含文件区块,无论访问的代码中是否有处理 ...