jzoj100044-abcd【多重揹包,二進位制壓縮,dp】
阿新 • • 發佈:2019-01-05
正題
題目大意
給出長度為
的序列
求一個序列
滿足
求
解題思路
我們把這個轉換成一個多重揹包問題,拿
個物品,要求價格之和為
,且價值最大。
我們可以發現對於每個物品我們都至少
個,所有我們可以直接把
個丟進揹包裡,然後每個物品數量變為
個,做多重揹包。
要二進位制壓縮,不然會
#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 210
using namespace std;
int n,m,tmp,num;
int a[N],b[N],c[N],d[N];
int w[10050],v[10050],f[100050];
int main()
{
memset(f,0xcf,sizeof(f));f[0]=0;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d%d%d",&a[i],&b[i],&c[i],&d[i]);
b[i]-=a[i];tmp+=a[i]*d[i];m-=a[i]*c[i];
}
for(int k=1;k<=n;k++)//二進位制壓縮
{
for(int i=1;i<=b[k];i*=2)
{
w[++num]=c[k]*i;v[num]=d[k]*i;
b[k]-=i;
}
if(b[k]) w[++num]=b[k]*c[k],v[num]=d[k]*b[k];
}
for(int i=1;i<=num;i++)//揹包
for(int j=m;j>=w[i];j--)
f[j]=max(f[j],f[j-w[i]]+v[i]);
printf("%d",f[m]+tmp);
}