超大背包问题(01背包)

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

这个问题给人的第一感觉就是普通的01背包。不过,看完数据范围会发现,这次价值和重量都可以是非常大的数值,相比之下n比较小。使用DP求解背包为题的复杂度是O(nW),因此不能用来解决这个问题。此时我们应该利用n比较小的特点来寻找其他方法。

挑选物品的方案总共有2^n种,所以不能直接枚举,但是如果将物品分成两半再枚举的话,由于每部分最多只有20个,这是可行的。我们把前半部分中的挑选方法对应的重量和价值总和记为w1、v1,这样在后半部分寻找总重w2 ≤ W - w1时使v2最大的选取方法即可。

因此,我们要思考从枚举得到的(w2,v2)集合中高效寻找max{v2|w2 ≤ W‘}的方法。首先,显然我们可以排除所有w2[i] ≤ w2[j] 并且 v2[i] >= v2[j]的j。这一点可以按照w2、v2的字典序排序后做到。此后剩余的元素都满足w2[i] < w2[j] <=> v2[i] < v2[j],要计算max{v2|w2 <= W‘}的话,只要寻找满足w2[i] <= W‘的最大的i就可以了。这可以用二分搜索完成,剩余的元素个数为M的话,一次搜索需要O(logM)的时间。因为M≤2^(n/2),所以这个算法总的时间复杂度是O(n
* 2^(n/2)),可以在实现内解决问题。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 50;
const long long INF = 0x3fffffff;
typedef long long LL;
int n;
LL w[N], v[N];
LL W;
pair <LL, LL> pi[1 << (N / 2)];

void solve() {
    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];
            }
        }
        pi[i] = make_pair(sw, sv);
    }

    sort(pi, pi + (1 << n2));
    int m = 1;
    for(int i = 1; i < (1 << n2); i++) {
        if(pi[m-1].second < pi[i].second) {
            pi[m++] = pi[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 += w[n2 + j];
                sv += v[n2 + j];
            }
        }
        if(sw <= W) {
            LL tv = (lower_bound(pi, pi + m, make_pair(W - sw, INF)) - 1)->second;
            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", &w[i], &v[i]);
        }
        solve();
    }
    return 0;
}
时间: 2024-10-09 20:53:04

超大背包问题(01背包)的相关文章

背包问题-01背包

*/--> 背包问题-01背包 Table of Contents 1 问题描述 2 问题思路 2.1 问题定义 2.2 实例演讲 3 问题思考 3.1 优化-定义问题 3.1.1 索引的改变 3.1.2 顺序的改变 3.2 优化-复杂度 3.3 初始值的思考 4 问题延伸 4.1 01背包问题的其他解法 4.2 01背包问题的实际引用 5 参考阅读 1 问题描述 背包问题主要分为三种:01背包 完全背包 多重背包. 01背包就是本文要讨论的问题. 有N件物品和一个容量为W的背包,每种物品 均只

【转】背包问题——“01背包”详解及实现(包含背包中具体物品的求解)

01背包是在M件物品取出若干件放在空间为W的背包里,每件物品的体积为C1,C2,…,Cn,与之相对应的价值为W1,W2,…,Wn.求解将那些物品装入背包可使总价值最大. 动态规划(DP): 1) 子问题定义:F[i][j]表示前i件物品中选取若干件物品放入剩余空间为j的背包中所能得到的最大价值. 2) 根据第i件物品放或不放进行决策                         (1-1) 其中F[i-1][j]表示前i-1件物品中选取若干件物品放入剩余空间为j的背包中所能得到的最大价值: 而

背包问题(01背包)

--------开始-------- 每次用到背包问题就忘,今天特意把背包问题写下来,本篇只写01背包问题,至于其它的背包问题以后会陆续出现,大多数背包问题都是以01背包为原型来演变过来的,所以先介绍经典的01背包问题. 01背包问题是动态规划的典型例题,0  1顾名思义就是一个物品有两种情况,拿或者不拿,每种物品有且仅有一件,用子问题定义状态:即f[i][j]表示前i件物品恰放入一个容量为j的背包可以获得的最大价值.则其状态转移方程便是: f[i][j]=max( f[i-1][j],f[i-

动态规划之背包问题-01背包+完全背包+多重背包

01背包 有n种不同的物品,每种物品分别有各自的体积 v[i],价值 w[i]  现给一个容量为V的背包,问这个背包最多可装下多少价值的物品. 1 for(int i = 1; i <= n; i++) 2 for(int j = V; j >= v[i]; j--) 3 dp[j] = max(dp[j], dp[j-v[i]]+w[i]); //dp[V]为所求 完全背包 01背包每种物品只能取一个, 完全背包即物品不记件数,可取多件. 1 for(int i = 1; i <= n

01背包与物品无限背包

一.01背包问题 01背包是在M件物品取出若干件放在空间为W的背包里,每件物品的体积为C1,C2,…,Cn,与之相对应的价值为W1,W2,…,Wn.求解将那些物品装入背包可使总价值最大. 动态规划: 1) 子问题定义:F[i][j]表示前i件物品中选取若干件物品放入剩余空间为j的背包中所能得到的最大价值. 2) 根据第i件物品放或不放进行决策 其中F[i-1][j]表示前i-1件物品中选取若干件物品放入剩余空间为j的背包中所能得到的最大价值: 而F[i-1][j-C[i]]+W[i]表示前i-1

01背包算法

转:01背包问题 动态规划的基本思想: 将一个问题分解为子问题递归求解,且将中间结果保存以避免重复计算.通常用来求最优解,且最优解的局部也是最优的.求解过程产生多个决策序列,下一步总是依赖上一步的结果,自底向上的求解. 动态规划算法可分解成从先到后的4个步骤: 1. 描述一个最优解的结构,寻找子问题,对问题进行划分. 2. 定义状态.往往将和子问题相关的各个变量的一组取值定义为一个状态.某个状态的值就是这个子问题的解(若有k个变量,一般用K维的数组存储各个状态下的解,并可根    据这个数组记录

超大背包(挑战编程之01背包)

先来温习01背包: 01背包是在M件物品取出若干件放在空间为W的背包里,每件物品的体积为W1,W2--Wn,与之相对应的价值为P1,P2--Pn. 求出获得最大价值的方案. 注意:在本题中,所有的体积值均为整数. 思路: 考虑用动态规划的方法来解决,这里的:阶段是:在前N件物品中,选取若干件物品放入背包中:状态是:在前N件物品中,选取若干件物品放入所剩空间为W的背包中的所能获得的最大价值:决策是:第N件物品放或者不放:由此可以写出动态转移方程:我们用f[i,j]表示在前 i 件物品中选择若干件放

1085 背包问题(0-1背包模板题)

1085 背包问题(0-1背包模板题)(51NOD基础题) 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 在N件物品取出若干件放在容量为W的背包里,每件物品的体积为W1,W2--Wn(Wi为整数),与之相对应的价值为P1,P2--Pn(Pi为整数).求背包能够容纳的最大价值. Input 第1行,2个整数,N和W中间用空格隔开.N为物品的数量,W为背包的容量.(1 <= N <= 100,1 <= W <= 10000) 第2 - N + 1行,每行

【动态规划】背包问题(一) 01背包 完全背包 多重背包

一.01背包 有N件物品和一个容量为V的背包.第i件物品的价格(即体积,下同)是w[i],价值是c[i].求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大. 这是最基础的背包问题,总的来说就是:选还是不选,这是个问题<( ̄ˇ ̄)/ 相当于用f[i][j]表示前i个背包装入容量为v的背包中所可以获得的最大价值. 对于一个物品,只有两种情况 情况一: 第i件不放进去,这时所得价值为:f[i-1][v] 情况二: 第i件放进去,这时所得价值为:f[i-1][v-c[i]]+w