B - 真·签到题 FZU - 2214(背包)
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(背包)的更多相关文章
- D - 下个也是签到题 FZU - 2221(博弈)
ZB loves watching RunningMan! There's a game in RunningMan called 100 vs 100. There are two teams, e ...
- HDU 6312.Game-博弈-签到题 (2018 Multi-University Training Contest 2 1004)
2018 Multi-University Training Contest 2 6312.Game 博弈,直接官方题解,懒了. 考虑将游戏变成初始时只有2~n,如果先手必胜的话,那么先手第一步按这样 ...
- 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 ...
- A 洛谷 P3601 签到题 [欧拉函数 质因子分解]
题目背景 这是一道签到题! 建议做题之前仔细阅读数据范围! 题目描述 我们定义一个函数:qiandao(x)为小于等于x的数中与x不互质的数的个数. 这题作为签到题,给出l和r,要求求. 输入输出格式 ...
- fjwc2019 D3T1 签到题 (贪心)
#184. 「2019冬令营提高组」签到题 每次询问接近O(1).......考虑贪心 怎么贪心呢? 对于相邻的两个数,我们要保证异或x后单调不降 我们找到两个数二进制上最高的相异位 当左边的数相异位 ...
- CTF-练习平台-WEB之 签到题
一.签到题 根据提示直接加群在群公告里就能找到~
- 洛谷P3601签到题(欧拉函数)
题目背景 这是一道签到题! 建议做题之前仔细阅读数据范围! 题目描述 我们定义一个函数:qiandao(x)为小于等于x的数中与x不互质的数的个数. 这题作为签到题,给出l和r,要求求. 输入输出格式 ...
- 【洛谷九月月赛T1】签到题(bsgs)(快速乘)
说好的签到题呢qwq....怎么我签到题都不会啊qwq 之后看了bsgs才发现貌似不是那么那么难fake!!什么东西... 先贴上部分分做法(也就是枚举1的个数,然后每一步都进行取模(这和最后取模结果 ...
- WEB新手之签到题
写一写web新手赛的题. 这是签到题,开始时需要耐心等待页面中字母全部出现. 字母全部出现后,会跳转到另一个界面,如上图所示.F12没什么特别的地方,这题应该有点难度. 按往常一样,先抓包. 按英文提 ...
随机推荐
- 如何用Eggjs从零开始开发一个项目(3)
上一篇中我们编写了用户注册登录.登录的代码,学习了如何进行用户的认证(JWT),如何安全地存储用的密码(hash).这一篇我们有以下2个任务: 获取token中的数据: 通过model来同步数据库. ...
- 下载HLS视频到本地
现在绝大多数网站播放视频都采用HLS技术,像腾讯优酷爱奇艺等等.本篇博文将介绍如何下载这样的视频到本地. 前言 因疫情影响,上课部分课程采用腾讯课堂上课,腾讯课堂有直播回放功能,但这个功能腾讯显然没有 ...
- .Net Core 3.1浏览器后端服务(四) 你眼中的依赖注入与我相同吗?
一.前言 DI-Dependency Injection 依赖注入 IoC-Inversion of Control 控制反转 近几年这依赖注入. 控制反转已成为软件开发中不可或缺的一部分,那么该怎么 ...
- 剑指 Offer 50. 第一个只出现一次的字符 + 哈希表 + 有序哈希表
剑指 Offer 50. 第一个只出现一次的字符 Offer_50 题目详情 方法一:使用无序哈希表 package com.walegarrett.offer; /** * @Author Wale ...
- JAVA-标识符、变量、数据类型
标识符和关键字 所有的标识符否应该以字母a ~ z和 A ~Z ,美元符($).下划线(_)开始. 首字符之后可以是字母a ~ z和 A ~Z ,美元符($).下划线(_)的任意字符组合. 注 ...
- FreeBSD 13 显卡支持
On FreeBSD 13, using drm-devel-kmod, support is the same as on Linux 5.4. This includes support for ...
- Flutter资源
目录 文章 一开始 HOWTO文档 网站/博客 高级 视频 组件 演示 UI 材料设计 图片 地图 图表 导航 验证 文字和富文本 分析.流量统计 自动构建 风格样式 媒体 音频 视频 语音 存储 获 ...
- 11、pass,is,位运算的补充
pass的补充 一般Python的代码是基于:和缩进来实现,Python中规定代码块中必须要有代码才算完整,在没有代码的情况下为了保证语法的完整性可以用pass代替 if 条件: pass else: ...
- 数字转人民币读法-python3
""" 2 把一个浮点数分解成证书备份和小数部分 3 """ 4 def divide(num): 5 intnum = int(num) ...
- python2文件开头两行
#!/usr/bin/python 或者 #!/usr/bin/env python 告诉操作系统python位置 # -*- coding:utf-8 -*- 设置文件编码为utf-8 (默认 ...