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 }

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

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

原文地址:https://www.cnblogs.com/ruruozhenhao/p/8908416.html

时间: 2024-10-10 13:15:21

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

XC1263 签到题(哇 ,写得我怀疑人生啊!!!@!@)

1263: 签到题 时间限制: 1 Sec  内存限制: 128 MB提交: 174  解决: 17 标签提交统计讨论版 题目描述 大家刚过完寒假,肯定还没有进入状态,特意出了一道签到题给各位dalao压压惊. 如果一个数字其中每一位都互不相同,则这个数满足要求.(如:21.10满足要求,11 不满足要求). 给出一个范围[a,b],并求出在范围内符合要求数字的数量. 输入 第一行T表示组数,T<=1000. 每一组输入一行,包含两个数字a,b.1<=a,b<=100000. 输出 对于

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

题目背景 这是一道签到题! 建议做题之前仔细阅读数据范围! 题目描述 我们定义一个函数:qiandao(x)为小于等于x的数中与x不互质的数的个数. 这题作为签到题,给出l和r,要求求. 输入输出格式 输入格式: 一行两个整数,l.r. 输出格式: 一行一个整数表示答案. 输入输出样例 输入样例#1: 233 2333 输出样例#1: 1056499 输入样例#2: 2333333333 2333666666 输出样例#2: 153096296 说明 对于30%的数据,. 对于60%的数据,.

hpu 1695 一道签到题

一道签到题 时间限制: 2 Sec  内存限制: 128 MB 提交: 69  解决: 33 [提交][状态][讨论版] 题目描述 我想说这是一道签到题,意思就是本次测试中最水的一道,不过我这样说你真的愿意相信我吗?哈哈,题目是这样的给你一下小数,然后请告诉我分别告诉我这个小数的循环节的循环次数.循环节以及循环节长度 输入 输入包括多组测试数据每组测试数据1行,包括一个小数,小数的长度不超过200,小数大于0小于100 输出 分别输出这个小数的循环节的长度.循环节以及循环次数,中间以一个空格间隔

acm集训训练赛A题【签到题】

一.题目 Description After winning gold and silver in IOI 2014, Akshat and Malvika want to have some fun. Now they are playing a game on a grid made of nhorizontal and m vertical sticks. An intersection point is any point on the grid which is formed by t

hdu4931 Happy Three Friends(BestCoder Round#4签到题)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4931 Happy Three Friends Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 150    Accepted Submission(s): 128 Problem Description Dong-hao , Grandpa

Codeforces Round #429 (Div. 2) 841A. Generous Kefa(签到题)

A. Generous Kefa One day Kefa found n baloons. For convenience, we denote color of i-th baloon as si - lowercase letter of the Latin alphabet. Also Kefa has k friends. Friend will be upset, If he get two baloons of the same color. Kefa want to give o

Codeforces Round #429 (Div. 2) 841B Godsend(签到题)

B. Godsend Leha somehow found an array consisting of n integers. Looking at it, he came up with a task. Two players play the game on the array. Players move one by one. The first player can choose for his move a subsegment of non-zero length with an

P3694 邦邦的大合唱站队/签到题(状压dp)

P3694 邦邦的大合唱站队/签到题 题目背景 BanG Dream!里的所有偶像乐队要一起大合唱,不过在排队上出了一些问题. 题目描述 N个偶像排成一列,他们来自M个不同的乐队.每个团队至少有一个偶像. 现在要求重新安排队列,使来自同一乐队的偶像连续的站在一起.重新安排的办法是,让若干偶像出列(剩下的偶像不动),然后让出列的偶像一个个归队到原来的空位,归队的位置任意. 请问最少让多少偶像出列? 输入输出格式 输入格式: 第一行2个整数N,M. 接下来N个行,每行一个整数a_i(1\le a_i

HLJU 1221: 高考签到题 (三分求极值)

1221: 高考签到题 Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 9  Solved: 4 [Submit][Status][Web Board] Description 在直角坐标系中有一条抛物线y=ax^2+bx+c和一个点P(x,y),求点P到抛物线的最短距离d. Input 多组数据. 5个整数a,b,c,x,y.前三个数构成抛物线的参数,后两个数x,y表示P点坐标.-200≤a,b,c,x,y≤200 Output 1个实数d,保留