超大背包(二分+贪心)
Posted yum20
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了超大背包(二分+贪心)相关的知识,希望对你有一定的参考价值。
Description
有重量和价值分别为 wi ( 1 ≤ wi ≤ 1015 )、vi ( 1 ≤ vi ≤ 1015 ) 的 n (1 ≤ n ≤ 40 )个物品。从这些物品中挑选总重量不超过 C (1 ≤ C ≤ 1015)的物品,求所选挑选方案中价值总和的最大值。
Input
多测试用例。每个测试用例:
第一行是 n 和 C,接下来有 n 行,每行两个正整数,分别是各个物品的 wi 和 vi
Output
每个测试用例输出一行:最大价值。
Sample Input
4 5
2 3
1 2
3 4
2 2
Sample Output
7
#include<iostream> #include<algorithm> #include<cstdio> #include <vector> #define LL long long //#define maxx 0x3f3f3f3f const LL inf=0x3f3f3f3f; using namespace std; pair<LL,LL> dp[1<<21];//重量,价值 int n,n2; LL C,sumw,sumv,ew,w[42],v[42]; int main(){ while(~scanf("%d %lld",&n,&C)){ for(int i=0;i<n;i++){ scanf("%lld %lld",&w[i],&v[i]); } n2=n/2; for(int i=0;i<(1<<n2);i++){//枚举前半部分,i的二进制的每一位算一种情况 sumw=0;sumv=0; for(int j=0;j<n;j++){ if(i>>j&1)//i<<n2种选择情况,判断此种情况是否需要加上去 { sumw+=w[j]; sumv+=v[j]; } } dp[i]=make_pair(sumw,sumv); } sort(dp,dp+(1<<n2));//把dp的重量从小到大排序 //贪心的做法,优化当前情况,排序后若价值与重量没法一致,则抛弃 int now=1; for(int i=1;i<(1<<n2);i++){ if(dp[now-1].second<dp[i].second){ dp[now++]=dp[i]; } } LL sum=0; for(int i=0;i<(1<<(n-n2));i++){ sumw=0;//printf("1 "); sumv=0; for(int j=0;j<(n-n2);j++){ if(i>>j&1){ sumw+=w[n2+j]; sumv+=v[n2+j]; }} if(sumw<=C) { //二分的做法找出第一个比maxx同样重量或更大时候,最大价值然而肯定没有,则减一便是最大 LL ew = (lower_bound(dp, dp + now, make_pair(C - sumw, inf)) - 1) -> second; sum=max(sum,sumv+ew); } } printf("%lld ",sum); } return 0; }
以上是关于超大背包(二分+贪心)的主要内容,如果未能解决你的问题,请参考以下文章
51nod 1257 背包问题 V3(这不是背包问题是二分)