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. 剑指 Offer 25. 合并两个排序的链表

    剑指 Offer 25. 合并两个排序的链表 Offer 25 该问题的原型就是多项式的合并. 实现较简单,没有特殊需要注意的问题. package com.walegarrett.offer; /* ...

  2. Java8的新特性--函数式接口

    目录 函数式接口 什么是函数式接口 函数式接口的使用 Java8内置的四大核心函数式接口 一.Consumer:消费型接口(void accept(T t)) 二.Supplier:供给型接口(T g ...

  3. 每日一题20201112(922. 按奇偶排序数组 II)

    题目链接: 922. 按奇偶排序数组 II 思路 很简单,搞懂问题的核心就行,假设现在有奇数在偶数位上,偶数在奇数位上. 那么我们要做的就是,找到分别在对方位置上的数字,然后交换他们就行. class ...

  4. 关于PHP的__construct()函数

    1 <?php 2 header("Content-Type:text/html;charset=utf-8");//调整为utf-8编码格式 3 class car 4 { ...

  5. Webpack 基石 tapable 揭秘

    Webpack 基于 tapable 构建了其复杂庞大的流程管理系统,基于 tapable 的架构不仅解耦了流程节点和流程的具体实现,还保证了 Webpack 强大的扩展能力:学习掌握tapable, ...

  6. android分析之Parcel

    将数据打包,跨进程传输(通过Binder).看看这货究竟是啥玩意: Parcel.java : public final class Parcel { private static final boo ...

  7. 怎么用Markdown在github上写书,并用pages展示

    怎么用git写书 安装环境 第一步 安装node npm 先检测自己电脑是否安装了node npm # 查看 node 版本 node -v # 查看 npm 版本 npm -v 复制代码 如果成功打 ...

  8. RPC 框架设计

    RPC 框架设计 初识 RPC 服务化有什么好处? 防止代码拷贝 防止底层复杂性的扩散 防止公共库的耦合 保证 SQL 的质量,能够解除数据库的耦合 什么是 RPC RPC:Remote Proced ...

  9. Python数据分析入门(一):搭建环境

    Python版本: 本课程用到的Python版本都是3.x.要有一定的Python基础,知道列表.字符串.函数等的用法. Anaconda: Anaconda(水蟒)是一个捆绑了Python.cond ...

  10. Android Studio详解项目中的资源

    •目录结构 •作用 所有以 drawable 开头的文件都是用来放图片的: 所有以 mipmap 开头的文件都是用来放应用图标的: 所有以 value 开头的文件夹都是用来放字符串.样式.颜色等配置的 ...