zoukankan      html  css  js  c++  java
  • #背包,位运算#洛谷 3188 [HNOI2007]梦幻岛宝珠

    题目


    分析

    既然对于每个(w_i)都能被分解为(a*2^b)
    那么考虑维护关于(b)的背包,再将关于(b)的背包统计为关于(b+1)的背包


    代码

    #include <cstdio>
    #include <cctype>
    #include <cstring>
    #define rr register
    using namespace std;
    int n,W,dp[31][1011],sw[101],w[101],c[101],ls[32],nxt[101];
    inline signed iut(){
        rr int ans=0,f=1; rr char c=getchar();
        while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
        while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
        return ans*f;
    }
    inline signed min(int a,int b){return a<b?a:b;}
    inline signed max(int a,int b){return a>b?a:b;}
    signed main(){
        while (1){
            memset(dp,0,sizeof(dp));
            memset(sw,0,sizeof(sw));
            memset(ls,0,sizeof(ls));
            n=iut(); W=iut(); rr int len;
            if (n==-1&&W==-1) return 0;
            for (rr int i=1,two;i<=n;++i){
                w[i]=iut(),c[i]=iut();
                for (two=0;!(w[i]&1);++two) w[i]>>=1;
                nxt[i]=ls[two],ls[two]=i,sw[two]+=w[i];
            }
            for (rr int i=0;i<=30;++i)
            for (rr int j=ls[i];j;j=nxt[j])
            for (rr int k=sw[i];k>=w[j];--k)
                dp[i][k]=max(dp[i][k],dp[i][k-w[j]]+c[j]);
            for (rr int i=1,t;i<=30;++i){
                sw[i]+=(sw[i-1]+1)>>1,t=(W>>(i-1))&1;
                for (rr int j=sw[i];j>=0;--j)
                for (rr int k=0;k<=j;++k)
                    dp[i][j]=max(dp[i][j],dp[i][j-k]+dp[i-1][min(sw[i-1],k<<1|t)]);//如果第$i-1$位为1还能够补1
            }
            for (len=0;W>>len;++len); --len;
            printf("%d
    ",dp[len][1]);
        }
    }
    
  • 相关阅读:
    关键字查询(含代码)
    数据表的基本操作(含代码)
    Java第一课!
    怎样学好 java ?
    01-C语言程序框架
    00-C语言概述
    RabbitMQ 数万个amq.gen-*的队列,导致内存溢出
    FFmpeg学习笔记1-C++编程
    C++ 应用程序发布相关问题
    动态链接库(DLL)
  • 原文地址:https://www.cnblogs.com/Spare-No-Effort/p/13922100.html
Copyright © 2011-2022 走看看