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

    给你N颗宝石,每颗宝石都有重量和价值。要你从这些宝石中选取一些宝石,保证总重量不超过W,且总价值最大为,并输出最大的总价值。数据范围:N<=100;W<=2^30,并且保证每颗宝石的重量符合a*2^b(a<=10;b<=30)

    Solution

    神仙背包。

    我们可以先对每个二进制位dp一下,然后从低到高位依次处理。

    合并操作比较麻烦。

    假设我们有一个容量为j的背包,我们要从上一层拿容量为k的物品,那么我们上一层需要的大小为k*2+(w>>i-1)&1,后面的是要满足w的二进制位,前面的是要贡献上去。

    Code

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #define N 32
    using namespace std;
    int dp[N][1002],e[N][102],val[N][102],ji[N],sum[N],n,w,ww,v,ans;
    const int ma=1000;
    int main(){
        while(1){
            scanf("%d%d",&n,&w);
            if(n<0)break;
            memset(dp,0,sizeof(dp));memset(e,0,sizeof(e));memset(val,0,sizeof(val));
            memset(ji,0,sizeof(ji));memset(sum,0,sizeof(sum));
            ans=0;
            for(int i=1;i<=n;++i){
                scanf("%d%d",&ww,&v);
                for(int j=30;j>=0;--j)
                  if(ww%(1ll<<j)==0){
                    e[j][++ji[j]]=ww/(1ll<<j),sum[j]+=ww/(1ll<<j),val[j][ji[j]]=v;
                    break;
                   }
            }
            for(int o=0;o<=30;++o)
              for(int i=1;i<=ji[o];++i)
                for(int j=sum[o];j>=e[o][i];--j)
                  dp[o][j]=max(dp[o][j],dp[o][j-e[o][i]]+val[o][i]);
            for(int i=1;i<=30;++i){
              sum[i]+=(sum[i-1]+1)/2;
              for(int j=sum[i];j>=0;--j)
                for(int k=0;k<=j;++k){
                  dp[i][j]=max(dp[i][j],dp[i][j-k]+dp[i-1][min(sum[i-1],2*k+((w>>i-1)&1))]); 
               }
             }
            printf("%d
    ",dp[30][0]);
        }
        return 0;
    }
  • 相关阅读:
    22个免费和高级WordPress的滑块插件
    asp.net mvc 4.0的部署
    苹果公布2011年度最佳iOS应用
    18 个 jQuery Mobile 开发贴士和教程
    给asp.net mvc小白扫盲用的
    JM8.6中的MV计算及上层块预测方法
    CAVLC算法解析
    JM8.6中的关于写比特流的问题
    JM8.6中对cofAC及相关数组的探讨
    JM8.6中三个RDCost函数的对比分析
  • 原文地址:https://www.cnblogs.com/ZH-comld/p/9818356.html
Copyright © 2011-2022 走看看