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

       

    超大背包问题

    • Time Limit: 2000/1000 MS (Java/Others)     Memory Limit: 65536/65536 K (Java/Others)
    • Total Submission(s): 17     Accepted Submission(s): 5
    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

     
    二分搜索,加一个贪心。
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int maxn=42;
     5 const ll inf=0x3f3f3f3f;
     6 
     7 int n;
     8 ll w[maxn],v[maxn];
     9 ll W;
    10 
    11 pair<ll,ll> ps[1<<(maxn/2)];
    12 
    13 int main()
    14 {
    15     ios::sync_with_stdio(0); std::cin.tie(0);
    16     while( cin >> n >> W){
    17         for(int i=0;i<n;i++)
    18             cin >> w[i] >> v[i];
    19 
    20         int N=n>>1; ///因为每个物品只有选与不选的操作,所以有两种选择,根据组合原理为2^n。
    21         ///但是2^n太大,可以分成两分进行搜索
    22         for(int i=0;i<(1<<N);i++){
    23             ll sumw=0,sumv=0;
    24             for(int j=0;j<N;j++){
    25                 if(i>>j&1){  ///先进行i>>j,即看选还是不选
    26                     sumw+=w[j];
    27                     sumv+=v[j];
    28                 }
    29             }
    30             ps[i]=make_pair(sumw,sumv);
    31         }
    32 //        for(int i=1;i<(1<<n2);i++){
    33 //            cout << ps[i].first << "  " << ps[i].second << endl;
    34 //        }
    35         sort(ps,ps+(1<<N)); ///对重量进行排序
    36 //        for(int i=1;i<(1<<n2);i++){
    37 //            cout << ps[i].first << "  " << ps[i].second << endl;
    38 //        }
    39         int m=1;
    40         for(int i=1;i<(1<<N);i++){
    41             if(ps[m-1].second < ps[i].second) ///若重量比前面元素大,价值却比前面小,就放弃。有贪心
    42               ps[m++]=ps[i];
    43         }
    44 
    45         ll ans=0;
    46         for(int i=0;i< 1<<(n-N);i++){
    47             ll sumw=0,sumv=0;
    48             for(int j=0;j<n-N;j++){ ///同上原理
    49                 if(i>>j&1){
    50                     sumw+=w[N+j];
    51                     sumv+=v[N+j];
    52                 }
    53             }
    54             if(sumw<=W){
    55                 ll tv=(lower_bound(ps,ps+m,make_pair(W-sumw,inf))-1)->second;
    56                 ///进行二分,找W-sumw后最大的价值,所以用lower_bound;
    57                 ans=max(ans,sumv+tv);
    58             }
    59         }
    60         cout << ans << endl;
    61     }
    62     return 0;
    63 }
  • 相关阅读:
    绕口令系列 1
    毕业论文排版
    使用matlab表示“段数不确定”的分段函数
    [转]C/C++关于全局变量和局部变量初始化与不初始化的区别
    [转]基于Protel DXP软件的PCB高级编辑技巧大全
    冒泡排序及其优化
    gcc编译器参数
    [转]跟我一起写Makefile系列
    实例说明optimize table在优化mysql时很重要
    log4php0.9的详细配备实例说明
  • 原文地址:https://www.cnblogs.com/ZQUACM-875180305/p/9033851.html
Copyright © 2011-2022 走看看