还是01背包
时间限制:10000 ms | 内存限制:228000 KB
难度:5
- 描述
-
有n个重量和价值分别为 wi 和 vi 的物品,从这些物品中挑选总重量不超过W的物品,求所有挑选方案中价值总和的最大值。- 输入
- 多组测试数据。
每组测试数据第一行输入n 和 W ,接下来有n行,每行输入两个数,代表第i个物品的wi 和 vi。
1 <= n <=40
1 <= wi <= 10^15
1 <= vi <= 10^15
1 <= W <= 10^15
- 输出
- 每组数据输出一行,代表挑选方案中价值总和的最大值。
- 样例输入
-
4 5 2 3 1 2 3 4 2 2
- 样例输出
-
7
- 来源
- 挑战程序设计
- 上传者
- TC_李远航
还没做。,先留作收藏
#include <iostream> #include <algorithm> #include <cstdio> #define Max(a,b) a>b?a:b #define INF 10000000000000000 using namespace std; typedef long long LL; const int MAX = 40; LL weight[MAX], value[MAX]; LL W; pair<LL, LL> ps[1 << (MAX / 2)]; int n; void slove() { //枚举前半部分 int n2 = n / 2; for (int i = 0; i < 1 << n2; i++)//前半部分的枚举总数为 2^(n/2); { LL sw = 0, sv = 0; //每种结果选取特定的价值和重量(i.e 一共2个东西,就一共四种情况,都不选,选第一个,选第二个,都选) for (int j = 0; j < n2; j++) { if (i >> j & 1) { sw += weight[j]; sv += value[j]; } } ps[i] = make_pair(sw, sv);//加入到ps数组中 } //对ps排序 sort(ps, ps + (1 << n2)); //ps 去重 int m = 1; for (int i = 1; i < 1 << n2; i++) if (ps[m - 1].second < ps[i].second) ps[m++] = ps[i]; LL res = 0;//保存结果 //枚举后半部分, 并且找到最优解 for (int i = 0; i < 1 << (n - n2); i++)//同样枚举的总个数 { LL sw = 0, sv = 0; for (int j = 0; j < n - n2; j++)//和前半部分的一样 { if (i >> j & 1) { sw += weight[n2 + j]; sv += value[n2 + j]; } } if (sw <= W)//加个判断求解最大价值,只有小于背包容量的时候 { LL tv = (lower_bound(ps, ps + m, make_pair(W - sw, INF)) - 1)->second;//找到前半部分对应的value res = Max(res, sv + tv); } } printf("%lld\n", res); } int main() { while (~scanf("%d %lld", &n, &W)) { for (int i = 0; i < n; i++) scanf("%lld %lld", &weight[i], &value[i]); slove(); } return 0; }
时间: 2024-10-03 23:02:57