标签:
有n个重量和价值分别为 wi 和 vi 的物品,从这些物品中挑选总重量不超过W的物品,求所有挑选方案中价值总和的最大值。
4 5 2 3 1 2 3 4 2 2
7
#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; }
标签:
原文地址:http://blog.csdn.net/yu_ch_sh/article/details/44263651