• CSU OJ PID=1514: Packs 超大背包问题,折半枚举+二分查找。


    1514: Packs

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 61  Solved: 4
    [Submit][Status][Web Board]

    Description

    Give you n packs, each of it has a value v and a weight w. Now you should find some packs, and the total of these value is max, total of these weight is equal to m.

    Input

    First line is a number T( T ≤ 5) represent the test cases.
    Then for each set of cases, first line is n (1 ≤ n ≤ 40) and m (1 ≤ m < 2^31), follow n line each is Wi (1 ≤ Wi < 2^31) and Vi (-2^31 < Vi < 2^31).

    Output

    Each case a line for max value.(Each set of inputs to ensure the solvability)

    Sample Input

    2
    3 3
    1 1
    2 2
    3 4
    5 2
    1 -5
    1 -8
    1 0
    1 -2
    1 5

    Sample Output

    4
    5

    注意:这里要求是满足总重量必须固定,而不是接近总重量。这就成了直接折半枚举,map大法就行了。


     1 #include <cstdio>
     2 #include <cstring>
     3 #include <cmath>
     4 #include <algorithm>
     5 #include <string>
     6 #include <vector>
     7 #include <set>
     8 #include <map>
     9 #include <stack>
    10 #include <queue>
    11 #include <sstream>
    12 #include <iomanip>
    13 using namespace std;
    14 typedef long long LL;
    15 const long long INF=99999999999999999LL;
    16 const int EXP=1e-5;
    17 const int MS=42;
    18 
    19 map<LL,LL> mp;
    20 int n;
    21 LL W;
    22 
    23 LL w[MS],v[MS];
    24 
    25 void solve()
    26 {
    27     mp.clear();
    28     int n1=n/2;
    29     for(int i=0;i<(1<<n1);i++)
    30     {
    31         LL sw=0,sv=0;
    32         for(int j=0;j<n1;j++)
    33         {
    34             if((i>>j)&1)
    35             {
    36                 sw+=w[j];
    37                 sv+=v[j];
    38             }
    39         }
    40         mp[sw]=max(mp[sw],sv);
    41     }
    42     LL ans=-INF;
    43     for(int i=0;i< 1<<(n-n1);i++)
    44     {
    45         LL sw=0,sv=0;
    46         for(int j=0;j<(n-n1);j++)
    47         {
    48             if((i>>j)&1)
    49             {
    50                 sw+=w[n1+j];
    51                 sv+=v[n1+j];
    52             }
    53         }
    54        if(mp.count(W-sw))
    55             ans=max(ans,mp[W-sw]+sv);
    56     }
    57     printf("%lld
    ",ans);
    58 }
    59 
    60 
    61 int main()
    62 {
    63     int T;
    64     scanf("%d",&T);
    65     while(T--)
    66     {
    67         scanf("%d%lld",&n,&W);
    68         for(int i=0;i<n;i++)
    69             scanf("%lld%lld",&w[i],&v[i]);
    70         solve();
    71     }
    72     return 0;
    73 }
    如果是重量不大于 W ,那么就要折半枚举+二分查找。

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <cmath>
      5 #include <algorithm>
      6 #include <string>
      7 #include <vector>
      8 #include <set>
      9 #include <map>
     10 #include <stack>
     11 #include <queue>
     12 #include <sstream>
     13 #include <iomanip>
     14 using namespace std;
     15 typedef long long LL;
     16 const int INF=0x4fffffff;
     17 const int EXP=1e-5;
     18 const int MS=40;
     19 
     20 int n;
     21 LL W;
     22 LL w[MS],v[MS];
     23 struct node
     24 {
     25     LL w,v;
     26     bool operator <(const node &a) const   //注意一定要加上const
     27     {
     28         return w<a.w||(w==a.w&&v<a.v);
     29     }
     30 }nodes[1<<(MS/2)];
     31 
     32 LL find(LL w,int cnt)
     33 {
     34     int l=0,r=cnt;
     35     while(r-l>1)         //  左闭右开区间处理起来更方便。
     36     {
     37         int mid=(l+r)/2;
     38         if(nodes[mid].w<=w)
     39             l=mid;
     40         else
     41             r=mid;
     42     }
     43     return nodes[l].v;
     44 }
     45 
     46 void solve()
     47 {
     48     int n1=n/2;
     49     int cnt=0;
     50     for(int i=0;i<(1<<n1);i++)
     51     {
     52         LL sw=0,sv=0;
     53         for(int j=0;j<n1;j++)
     54         {
     55             if((i>>j)&1)
     56             {
     57                 sw+=w[j];
     58                 sv+=v[j];
     59             }
     60         }
     61         nodes[cnt].w=sw;
     62         nodes[cnt++].v=sv;
     63     }
     64     sort(nodes,nodes+cnt);
     65     int last=0;
     66     for(int i=0;i<cnt;i++)
     67     {
     68         if(nodes[last].v<nodes[i].v)
     69         {
     70             nodes[++last]=nodes[i];
     71         }
     72     }
     73     cnt=last+1;
     74     LL ans=0;
     75     for(int i=0;i< 1<<(n-n1);i++)
     76     {
     77         LL sw=0,sv=0;
     78         for(int j=0;j<(n-n1);j++)
     79         {
     80             if((i>>j)&1)
     81             {
     82                 sw+=w[n1+j];
     83                 sv+=v[n1+j];
     84             }
     85         }
     86         if(sw<=W)
     87         {
     88             LL tv=find(W-sw,cnt);
     89             ans=max(ans,sv+tv);
     90         }
     91     }
     92     printf("%lld
    ",ans);
     93 }
     94 
     95 
     96 int main()
     97 {
     98     int T;
     99     scanf("%d",&T);
    100     while(T--)
    101     {
    102         scanf("%d%lld",&n,&W);
    103         for(int i=0;i<n;i++)
    104             scanf("%lld%lld",&w[i],&v[i]);
    105         solve();
    106     }
    107     return 0;
    108 }
     
     
  • 相关阅读:
    spring cloud项目搭建
    获取iframe的window对象
    数学杂谈 #7
    [AGC023D] Go Home
    JOISC 2021 部分题解
    [NOI2017]泳池
    [NOI2016] 循环之美
    [NOI2016] 优秀的拆分
    [LG P3676]小清新数据结构题
    [ARC113F]Social Distance
  • 原文地址:https://www.cnblogs.com/767355675hutaishi/p/4388362.html
Copyright © 2020-2023  润新知