hdu 2844 多重背包+单调队列优化

思路:把价值看做体积,而价值的大小还是其本身,那么只需判断1-m中的每个状态最大是否为自己,是就+1;

#include<iostream>

#include<algorithm>

#include<cstring>

#include<cstdio>

#define Maxn 100010

#define Max(a,b) (a)>(b)?(a):(b)

using namespace std;

int dp[Maxn],num[110],v[110];

struct Que{

    int pos,val;

}que[Maxn*2];

int main()

{

    int n,m,i,j;

    while(scanf("%d%d",&n,&m)!=EOF,n&&m)

    {

        memset(dp,0,sizeof(dp));

        for(i=1;i<=n;i++)

            scanf("%d",v+i);

        for(i=1;i<=n;i++)

            scanf("%d",num+i);

        int d;

        int cnt;

        for(i=1;i<=n;i++)

        {

            if(v[i]>m) continue;

            if(v[i]*num[i]>=m) {for(j=v[i];j<=m;j++) dp[j]=Max(dp[j],dp[j-v[i]]+v[i]); continue;}

            for(d=0;d<v[i];d++)

            {

                int head=1,rear=0;

                for(j=0;j<=(m-d)/v[i];j++)

                {

                    while(head<=rear&&que[rear].val<dp[j*v[i]+d]-j*v[i])

                        rear--;

                    que[++rear].val=dp[j*v[i]+d]-j*v[i],que[rear].pos=j;

                    if(que[head].pos<j-num[i]) head++;

                    dp[j*v[i]+d]=que[head].val+j*v[i];

                }

            }

        }

        cnt=0;

        for(i=1;i<=m;i++)

            if(dp[i]==i)

             cnt++;

        printf("%d\n",cnt);

    }

    return 0;

}

 

你可能感兴趣的:(HDU)