BZOJ 1190 梦幻岛宝珠

Posted on 2017-03-15 15:42  ziliuziliu  阅读(188)  评论(0编辑  收藏  举报

二进制分组背包。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,w;
long long f[45][1050],x,y;
int main()
{
    while (scanf("%d%d",&n,&w)==2)
    {
        memset(f,0,sizeof(f));
        if (n==-1 && w==-1) break;
        for (int i=1;i<=n;i++)
        {
            scanf("%lld%lld",&x,&y);
            int a,b=0;
            while (!(x&1)) {x>>=1;b++;}
            a=x;
            for (int j=1000;j>=a;j--) f[b][j]=max(f[b][j],f[b][j-a]+y);
        }
        for (int i=0;i<=30;i++)
            for (int j=1;j<=1000;j++)
                f[i][j]=max(f[i][j],f[i][j-1]);
        long long ans=0;
        for (int i=1;i<=1000;i++) ans=max(ans,f[0][i]);
        for (int i=1;i<=30 && (1<<i)<=w;i++)
            for (int j=min(1000,w>>i);j>=0;j--)
                for (int k=0;k<=j;k++)
                {
                    f[i][j]=max(f[i][j],f[i][j-k]+f[i-1][min(2*k+(((w>>(i-1))&1)>0),1000)]);
                    ans=max(ans,f[i][j]);
                }
        printf("%lld\n",ans);
    }
    return 0;
}