超大背包问题

Posted cadcadcad

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了超大背包问题相关的知识,希望对你有一定的参考价值。

超大背包问题

输入条件:(1le nle40,1le w_i,v_ile10^{15},1le Wle 10^{15})

解法:因为不能够再像前面的背包问题一样,把背包容量作为状态来储存了,因为开不了那么大的空间,那么就应该好好利用 n 很小的这个优势,但是如果全部遍历的话,复杂度就是(O(2^n))很明显这也不能跑完,但是我们可以利用折半枚举,来降低其复杂度,这样复杂度就只有(O(2^{n/2}n))了。

// Created by CAD on 2020/2/2.
#include <bits/stdc++.h>
#define se second
#define INF 0x7fffffffffffffff
#define pll pair<long long,long long>
#define ll long long
using namespace std;

const int maxn=45;
ll w[maxn],v[maxn];
ll W;
pll p[1<<(maxn/2)];
int main()
{
    int n;  cin>>n>>W;
    for(int i=1;i<=n;++i)
        cin>>w[i]>>v[i];
    int n1=n/2;
    for(int i=0;i<1<<n1;++i){
        ll sw=0,sv=0;
        for(int j=0;j<n1;++j)
            if(i>>j&1) sw+=w[j],sv+=v[j];
        p[i]={sw,sv};
    }
    sort(p,p+(1<<n1));
    int m=1;
    for(int i=0;i<1<<n1;++i)
        if(p[m-1].se<p[i].se) p[m++]=p[i];
    ll ans=0;
    for(int i=0;i<1<<(n-n1);++i)
    {
        ll sw=0,sv=0;
        for(int j=0;j<n-n1;++j)
            if(i>>j&1) sw+=w[n1+j],sv+=v[n1+j];
        if(sw<=W){
            ll t=(lower_bound(p,p+m,make_pair(W-sw,INF))-1)->se;
            ans=max(ans,sv+t);
        }
    }
    cout<<ans<<'
';
    return 0;
}

以上是关于超大背包问题的主要内容,如果未能解决你的问题,请参考以下文章

超大背包问题

ZOJ 3631 Watashi's BG(超大背包问题)

Born Slippy (超大背包问题 + 树形DP)

超大背包

nyoj 1091 还是01背包(超大数)

超大背包(二分+贪心)