题解:P11297 [NOISG2018 Prelim] Knapsack
WangYongkai__AFO · · 题解
前置芝士:多重背包的二进制优化或单调队列优化
双倍经验:
https://www.luogu.com.cn/problem/P1776
Solution:
思路:
首先我们看题意,仔细思考可以看出这是个多重背包 DP ,因为每个物品有多个,所以我们可以考虑多重背包的二进制优化,(其实单调队列的优化也可以,但是相比二进制优化比较难理解而且不是很好写),想要学习单调队列优化的同学可以去上面双倍经验的题解学习一下。
优化讲解:
什么是二进制优化呢?我们可以举个例子。以 15 为例,
优化后结合背包板子即可,不想挂分的话记得数组开大一点
Codes:
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<stack>
#include<queue>
#include<map>
#include<vector>
#include<cstdio>
#include<set>
#include<bitset>
#include<iomanip>
using namespace std;
int s,n;
const int N=1e7+5;
long long v[N],w[N],k[N],dp[N];
signed main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>s>>n;
long long a,b,c,cnt=0;
for(int i=1;i<=n;i++)
{
cin>>a>>b>>c;
long long k=1;
while(k<=c)
{
v[++cnt]=k*a,w[cnt]=k*b;
c-=k;
k*=2;
}
if(c)
{
v[++cnt]=a*c,w[cnt]=b*c;
}
}
for(int i=1;i<=cnt;i++)
{
for(int j=s;j>=w[i];j--)
{
dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
}
}
cout<<dp[s];
return 0;
}