【JZOJ100044】abcd【DP】【揹包】
阿新 • • 發佈:2018-12-31
題目大意:
題目連結:https://jzoj.net/senior/#main/show/100044
題目圖片:
http://wx4.sinaimg.cn/mw690/0060lm7Tly1fy7h522lqej30j50dk3zl.jpg
http://wx4.sinaimg.cn/mw690/0060lm7Tly1fy7h522g0rj30jv0h3glu.jpg
http://wx1.sinaimg.cn/mw690/0060lm7Tly1fy7h5226qpj30j204vgli.jpg
給定
四個陣列,求
,使得
求 。
思路:
看得出是一個多重揹包嗎?
對於第
個“物品”:
- 價值
- 重量
- 個數
首先,由於必須選擇至少
個物品
,所以就直接取走
個物品
。剩餘
個物品
。
那麼就是一個模板的多重揹包了。
用二進位制拆分變成
揹包,然後求出
,最終答案就是
必須選的部分。
程式碼:
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int N=200010;
int n,m,s,a,b,c,d,ans,sum,w[N],v[N],f[N];
int main()
{
scanf("%d",&s);
while (s--)
{
scanf("%d%d%d%d",&a,&b,&c,&d);
sum+=a*d; //必須選
m-=a*c;
b-=a;
for (int i=1;i<=b;i*=2) //二進位制拆分
{
w[++n]=i*c;
v[n]=i*d;
b-=i;
}
if(b) w[++n]=b*c,v[n]=b*d;
}
memset(f,0x80,sizeof(f));
f[0]=0;
for (int i=1;i<=n;i++) //揹包
for (int j=m;j>=w[i];j--)
f[j]=max(f[j],f[j-w[i]]+v[i]);
printf("%d\n",f[m]+sum);
return 0;
}