zoukankan      html  css  js  c++  java
  • 超大背包问题

    使用dp求解复杂度过高,利用n比较小的特点。

    折半枚举,把前半部分中的选取方法对应的重量和价值总和记为w1,v1,这样在后半部分寻找总重w2<=W-w1时使v2最大的选取方法就好。

    首先排除所有w2[i]<=w2[j]&&v2[i]>=v1[j]的j。这一点可以按照w2,v2的字典序排序后做到。

    此后剩余的元素都满足w2[i]<w2[j]&&v2[i]<v2[j],要计算max{v2|w2<=W'},只要寻找满足w2[i]<=W'的最大i即可,用二分搜索完成。

    #include<iostream>
    #include<math.h>
    #include<algorithm>
    #include<stdio.h>
    #define INF 10000000
    typedef long long ll;
    using namespace std;
    int n;
    ll w[41],v[41],W;
    pair<ll,ll> ps[1<<21];
    int main()
    {
        cin>>n;
        for(int i=0;i<n;i++)
        {
            cin>>w[i]>>v[i];
        }
        cin>>W;
        //枚举前半部分 二进制枚举
        int n2=n/2;
        for(int i=0;i<1<<n2;i++)
        {
            ll sw=0,sv=0;
            for(int j=0;j<n2;j++)
            {
                if(i>>j&1)
                {
                    sw+=w[j];
                    sv+=v[j];
                }
            }
            ps[i]=make_pair(sw,sv);
        }
    
        //去掉多余元素(价值小重量大)
        sort(ps,ps+(1<<n2));
        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(j>>i&1)
                {
                    sw+=w[n2+j];
                    sv+=v[n2+j];
                }
            }
            if(sw<=W)
            {
                //找到前半部分中加起来不超重的价值最大者
                ll tv=(lower_bound(ps,ps+m,make_pair(W-sw,(ll)INF))-1)->second;
                res=max(res,sv+tv);
            }
        }
        cout<<res<<endl;
        return 0;
    }
    View Code
  • 相关阅读:
    移动运营四:如何优化页面布局
    移动运营三:如何进行场景洞察
    移动运营二:如何更加了解你的用户
    移动运营一:如何进行运营效果分析
    操作系统的系统调用
    从图灵机到操作系统的启动
    伸展树(splay tree)
    AVL树
    二叉搜索树
    表达式树
  • 原文地址:https://www.cnblogs.com/wangkaipeng/p/6502947.html
Copyright © 2011-2022 走看看