AcWing 4. 多重背包问题 I O(n^3)
#include<bits/stdc++.h>
using namespace std;
const int N = 110;
int n,m;
int f[N];
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
int v,w,s;
cin>>v>>w>>s;
for(int j=m;j>=0;j--)
for(int k=1;k<=s && k*v<=j;k++)
f[j]=max(f[j],f[j-k*v]+k*w);
}
cout<<f[m];
return 0;
}
AcWing 5. 多重背包问题 II 当N,M,K都是上千的话,我们需要优化(二进制优化)
多重背包---->01背包,第i个物品有s个,我们就把它拆成s份放到物品组中去,直接拆的话数量也是多,也会TLE
二进制的拆法:
0~7:1 2 4的选法,即log2(x)上取整
如果是0~10的话,不能直接用1 2 4 8,因为这样可以枚举到0~15的所有数,所以我们需要对最后一个数进行减操作
即 1 2 4 3 ,物品x份,直接变成log(x)份 这道题复杂度:1000 * 11 * 2000 = 2*10^7
#include<bits/stdc++.h>
using namespace std;
const int N = 2020;
int n,m,f[N];
struct Goods
{
int v,w;
};
int main()
{
vector<Goods> goods;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
int v,w,s;
cin>>v>>w>>s;
for(int k=1;k<=s;k*=2)
{
s-=k;
goods.push_back({v*k,w*k});
}
if(s>0) goods.push_back({v*s,w*s});
}
for(auto good:goods)
for(int j=m;j>=good.v;j--)
f[j]=max(f[j],f[j-good.v]+good.w);
cout<<f[m];
return 0;
}
数据范围
0<N≤10000<N≤1000
0<V≤200000<V≤20000
0<vi,wi,si≤20000
这个时候就需用单调队列进行优化