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

    超大背包问题:有n个重量和价值分别为w[i]和v[i]的物品,从这些物品中挑选总重量不超过W的物品,求所有挑选方案中价值总和的最大值。其中,1 ≤ n ≤ 40, 1 ≤ w[i], v[i] ≤ 10^15, 1 ≤ W ≤ 10^15.

    按照普通的DP 思路显然是无法求解的, 背包的体积太大了, 那么就要换种思考的方向,观察物品的数量只有 40 个,普通的枚举话 2 ^ 40,肯定是超时,那么如何是分成两堆呢 ? 在按照字典序去枚举,不就没问题了吗 ?

    int n, W;
    int v[50], w[50];
    
    struct node
    {
        int ww, vv;
        node(int _w = 0, int _v = 0):ww(_w), vv(_v){}
        
    }pre[1<<25];
    
    bool cmp(node a, node b){
        if (a.vv == b.vv) return a.ww > b.ww;
        else return a.vv < b.vv;
    }
    int ans;
    
    int fun(int l, int r, int key){
        while(l <= r){
            int mid = (l + r) >> 1;
            if (pre[mid].vv == key) return pre[mid].ww;
            else if (pre[mid].vv < key) l = mid + 1;
            else r = mid - 1;
        }
        return pre[r].ww;
    }
    
    void solve(){
        int n2 = n / 2;
        for(int i = 0; i < 1 << n2; i++){
            int sv = 0, sw = 0;
            for(int j = 0; j < n2; j++){
                if ((i >> j) & 1){
                    sw += w[j];
                    sv += v[j];
                }
            }
            pre[i] = node(sw, sv);    
        }
        sort(pre, pre+ (1 << n2), cmp);
        int m = 0;
        for(int i = 1; i < 1<<n2; i++){
            if (pre[m].ww < pre[i].ww){
                pre[++m] = pre[i];
            }
        }
        ans = 0;
        for(int i = 0; i < 1<<(n-n2); i++){
            int sv = 0, sw = 0;
            for(int j = 0; j < (n-n2); j++){
                if ((i >> j) & 1){
                    sw += w[n2+j];
                    sv += v[n2+j];
                }
            }
            if (sv <= W){         
                int f = fun(0, m, W-sv);
                ans = max(ans, f + sw); 
            }
        }
    }
    
    int main() {
        //freopen("in.txt", "r", stdin);
        //freopen("out.txt", "w", sttout);
        
        while(~scanf("%d%d", &n, &W)){
            for(int i = 0; i < n; i++){
                scanf("%d%d", &v[i], &w[i]);
            }
            solve();
            printf("%d
    ", ans);
        }
        return 0;
    }
    /*
    4 5
    2 3
    1 2
    3 4
    2 2
    */
    
    东北日出西边雨 道是无情却有情
  • 相关阅读:
    mysql之SQL入门与提升(一)
    数据库的主键和外键
    mysql项目实战经验
    浅谈设计模式
    记录下sparkStream的做法(scala)
    hive-hbase-handler方式导入hive表数据到hbase表中
    订单风险系统BI
    关于maven 把插件依赖一起打包进jar问题
    一些hbase的shell查询语句
    关于hive表同步类型问题
  • 原文地址:https://www.cnblogs.com/ccut-ry/p/7861956.html
Copyright © 2011-2022 走看看