zoukankan      html  css  js  c++  java
  • BZOJ 1190 梦幻岛宝珠(分组01背包)

    跑了7000ms。。。

    这是个体积和价值都超大的背包。但是体积保证为a*2^b的(a<=10,b<=30)形式.且n<=100.

    于是可以想到按b来分组。这样的话每组最多为a*n*2^b的体积。把每个分组进行一次01背包。

    令dp[i][j]表示体积为j*2^i+w&(1<<i)的最大价值。再把每个分组背包做一次01背包,随便转移一下就行了。

    # include <cstdio>
    # include <cstring>
    # include <cstdlib>
    # include <iostream>
    # include <vector>
    # include <queue>
    # include <stack>
    # include <map>
    # include <set>
    # include <cmath>
    # include <algorithm>
    using namespace std;
    # define lowbit(x) ((x)&(-x))
    # define pi acos(-1.0)
    # define eps 1e-9
    # define MOD 1000000000
    # define INF 1000000000
    # define mem(a,b) memset(a,b,sizeof(a))
    # define FOR(i,a,n) for(int i=a; i<=n; ++i)
    # define FO(i,a,n) for(int i=a; i<n; ++i)
    # define bug puts("H");
    # define lch p<<1,l,mid
    # define rch p<<1|1,mid+1,r
    //# define mp make_pair
    # define pb push_back
    typedef pair<int,int> PII;
    typedef vector<int> VI;
    # pragma comment(linker, "/STACK:1024000000,1024000000")
    typedef long long LL;
    int Scan() {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    void Out(int a) {
        if(a<0) {putchar('-'); a=-a;}
        if(a>=10) Out(a/10);
        putchar(a%10+'0');
    }
    const int N=105;
    //Code begin...
    
    int dp[35][1005];
    
    int main ()
    {
        int n, W, x, val, wei, tmp;
        while (scanf("%d%d",&n,&W)) {
            if (n==-1) break;
            tmp=W; wei=0; mem(dp,0);
            while (tmp) ++wei, tmp>>=1;
            FOR(i,1,n) {
                scanf("%d%d",&x,&val);
                int num=0;
                while (x) {
                    ++num;
                    if (x&1) break;
                    x>>=1;
                }
                for (int i=1000; i>=x; --i) dp[num][i]=max(dp[num][i],dp[num][i-x]+val);
            }
            FOR(i,1,wei) for (int j=1000; j>=0; --j) for (int k=j; k>=0; --k) {
                int l=min(((j-k)<<1)+((W>>(i-2))&1),1000);
                dp[i][j]=max(dp[i][j],dp[i][k]+dp[i-1][l]);
            }
            printf("%d
    ",dp[wei][1]);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    java 多线程(synchronized)
    java 多线程(daemon)
    【转】 Nginx深入详解之多进程网络模型
    Linux 网络编程(epoll)
    Linux 网络编程(多路复用)
    Linux 网络编程(UDP)
    Linux 网络编程(TCP)
    STM32F0xx_看门狗(独立+窗口)配置详细过程
    STM32F0xx_FLASH编程(片内)配置详细过程
    STM32F0xx_RTC实时时钟配置详细过程
  • 原文地址:https://www.cnblogs.com/lishiyao/p/6782213.html
Copyright © 2011-2022 走看看