zoukankan      html  css  js  c++  java
  • 分层背包 [HNOI2007]梦幻岛宝珠

    问题 I: [HNOI2007]梦幻岛宝珠
    时间限制: 1 Sec 内存限制: 162 MB
    提交: 32 解决: 6
    [提交][状态][讨论版]
    题目描述
    给你N颗宝石,每颗宝石都有重量和价值。要你从这些宝石中选取一些宝石,保证总重量不超过W,且总价值最大为,并输出最大的总价值。数据范围:N<=100;W<=2^30,并且保证每颗宝石的重量符合a*2^b(a<=10;b<=30)

    输入
    输入文件中包含多组数据。每组数据的格式如下:第一行是两个正整数n和W,1≤n≤100,1≤W≤2^30,分别表示宝石的数目和最多能带走的宝石重量。接下来的n行,每行有两个正整数weighti和valuei,1≤weighti≤2^30, 0≤valuei≤2^30,分别表示第i颗宝石的重量和价值,且保证weighti能写成a*2^b(1≤a≤10,0≤b≤30)的形式。同一行的两个正整数之间用空格隔开。最后一组数据的后面有两个-1,表示文件的结束。这两个-1并不代表一组数据,你不需对这组数据输出结果。并且输入文件中数据的组数不超过20。

    输出
    对于输入的每组数据,输出一个整数C,表示小P最多能带走的宝石的总价值。每个结果整数C单独占一行,且保证C不会超过2^30。

    样例输入
    4 10
    8 9
    5 8
    4 6
    2 5
    4 13
    8 9
    5 8
    4 6
    2 5
    16 75594681
    393216 5533
    2 77
    32768 467
    29360128 407840
    112 68
    24576 372
    768 60
    33554432 466099
    16384 318
    33554432 466090
    2048 111
    24576 350
    9216 216
    12582912 174768
    16384 295
    1024 76
    -1 -1
    样例输出
    14
    19
    1050650

    我一直以为01背包是很基础很基础的题,然而碰到了他:分层01背包,不同层之间还有转移关系。成功被虐爆。
    总容量的范围。。。时空间都撑不住。但我们发现每个物品都是a*2^b,总容量也是可以分解成多个2的几次方。。。按位分层?!!记录物品重量在哪一层上,分层进行背包。f[i][j]表示容量在2^i那一位上剩余j(就是剩下j*2^i)
    分层背包很简单,最重要的就是层与层之间的转移。从最高位向最低位转移。当前位跑完后对较小1位转移。
    f[i-1][j*2+s[i-1]]=max(f[i-1][2*j+s[i-1]],f[i][j])
    s[i-1]为总容量在i-1上是否有1.这个意思是第i位上剩下了j*2^i,并把它留给下一位使用,到了下一位就变成了j*2*2^(i-1),再加上本来总容量就存在的1,也就是上面的式子了。
    但多层的“剩下”会使j重新爆炸,但明显剩下来太多一定不优,定个上界(1000应该就够)就行了。
    做了好几天。。。抄了POPOQQQ的标程,但发现数据强的点会TLE…..然后找了另一个,发现和自己最初yy出来的只差那么几行(但我yy的程序只能过样例)。。。达哥lrd推荐我如果打得头晕眼花可以先放放。。。差点死在这题手里。

    #include <cstdio>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <vector>
    #define ll long long
    using namespace std;
    int read()
    {
        int sum=0,f=1;char x=getchar();
        while(x<'0'||x>'9'){if(x=='-')f=-1;x=getchar();}
        while(x>='0'&&x<='9'){sum=(sum<<3)+(sum<<1)+x-'0';x=getchar();}
        return sum*f;
    }
    int t,n,m,h,ans,w[105],v[105],f[33][10005],s[35];
    vector<int> ve[35];
    int main()
    {
        while(1)
        {
            n=read();m=read();if(n==-1&&m==-1)break;
            memset(f,-0x3f,sizeof(f));
            memset(s,0,sizeof(s));ans=0;
            for(int i=0;i<=30;i++)ve[i].clear();
            for(int j=0;j<=30;j++)
                if((1<<j)&m)s[j]=1,h=j;
            for(int i=1;i<=n;i++)
            {
                w[i]=read();v[i]=read();
                int sum=0;
                while(w[i]%2==0)w[i]/=2,sum++; 
                ve[sum].push_back(i);
            }
            for(int i=h;~i;i--)
            {
                f[i][s[i]]=max(f[i][s[i]],0);
                for(int k=0;k<ve[i].size();k++)
                {
                    int x=ve[i][k];
                    for(int j=w[x];j<=2000;j++)
                        f[i][j-w[x]]=max(f[i][j-w[x]],f[i][j]+v[x]);
                }
                if(i)
                    for(int j=0;j<=2000;j++)
                           f[i-1][min(j*2+s[i-1],2000)]=max(f[i-1][min(2000,j*2+s[i-1])],f[i][j]);
                else 
                    for(int j=0;j<=2000;j++)ans=max(ans,f[i][j]);
            }
            printf("%d
    ",ans);
        }
    }
  • 相关阅读:
    119. Pascal's Triangle II
    118. Pascal's Triangle
    112. Path Sum
    111. Minimum Depth of Binary Tree
    110. Balanced Binary Tree
    108. Convert Sorted Array to Binary Search Tree
    88. Merge Sorted Array
    83. Remove Duplicates from Sorted List
    70. Climbing Stairs
    陌陌面试经历
  • 原文地址:https://www.cnblogs.com/QTY2001/p/7688756.html
Copyright © 2011-2022 走看看