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. Linux 安装python 模块及库

    转载于https://blog.csdn.net/csdn_am/article/details/79924744 有时我们使用下载python 自带的pip 安装一些工具包时,会报如下错误 找不到满 ...

  2. SpringCloud(三):SpringCloud快速开发入门

    3-1.  搭建和配置一个服务提供者 我们知道,SpringCloud 构建微服务是基于 SpringBoot 开发的.(如果SpringBoot不会的可以先看SpringBoot专栏) 1. 创建一 ...

  3. Kubernetes-1.概述

    内容主要摘自官网文档资料 官方地址 概述Kubernetes基本信息 前提条件: 掌握容器或Docker知识 文档编写基于kubernetes v1.17版本 目录 概述 Kubernetes对象 K ...

  4. HDFS 03 - 你能说说 HDFS 的写入和读取过程吗?

    目录 1 - HDFS 文件的写入 1.1 写入过程 1.2 写入异常时的处理 1.3 写入的一致性 2 - HDFS 文件的读取 2.1 读取过程 2.2 读取异常时的处理 版权声明 1 - HDF ...

  5. 后端程序员之路 27、LogStash

    访谈与书评:<LogStash,使日志管理更简单>http://www.infoq.com/cn/articles/review-the-logstash-book/ [Logstash] ...

  6. Android - 利用扩展函数为Bitmap添加文字水印

    <异空间>项目技术分享系列--扩展函数为Bitmap添加文字水印 对图片Bitmap绘制文字水印还是比较常见的需求,毕竟版权意识都在增强(用户可以给自己图片加上用户名),还可以为用户提供更 ...

  7. System.IO.IOException:“找不到资源“window1.xaml”。” 解决方法

    报错:找不到资源"window1.xaml 原因:在编译时使用的是en-US选项进行编译并生成了en-US为名的文件夹,里面包含了可本地化的内容:但是你的本地系统使用的是zh-CN,在你运行 ...

  8. React源码 commit阶段详解

    转: React源码 commit阶段详解 点击进入React源码调试仓库. 当render阶段完成后,意味着在内存中构建的workInProgress树所有更新工作已经完成,这包括树中fiber节点 ...

  9. SpringMVC-01 什么是SpringMVC

    SpringMVC-01 什么是SpringMVC 回顾MVC 1.什么是MVC MVC是模型(Model).视图(View).控制器(Controller)的简写,是一种软件设计规范. 是将业务逻辑 ...

  10. 关于个Base64,MD5,16进制的转换

    1,待签名数据以UTF-8的格式转字节流,对字节流进行MD5算法得到的签名字节流,再转换为16进制字符串,即生成了数字签名. byte[] targetData = md5.ComputeHash(S ...