题目链接:https://www.acwing.com/problem/content/5/
最近没有比赛可打,好好看看基础。
多重背包的朴素写法很简单,基本上都能写,复杂度nmk级别的,在数据量几千的情况下就处理不了了。
因此我们考虑用空间换时间,对物品进行二进制优化,“将物品变得多多的”,例如7 ,我们可以看成 1 2 4 ,也就是1倍价值1倍重量看做一个物品,2倍价值2倍重量看做一个物品,4倍价值4倍重量看做一个物品...依次类推,这样一个物品就被划分成了 logk 件物品。这里面的具体操作是一个累减的过程。
这样在空间上就增加了,因此我们再用01背包的时候有必要对其进行空间优化,优化成一维的dp。
code:
#include<bits/stdc++.h> using namespace std; #pragma GCC optimize(2) inline int read() { int x=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} return x*f; } const int nn = 2010; int n,m; int v,w,s; struct wupin{ int v,w; }; vector<wupin> ve; int f[nn]; int main() { cin>>n>>m; while(n--){ cin>>v>>w>>s; ve.push_back({0,0}); for(int i=1;i<=s;i*=2){ s-=i; ve.push_back({v*i,w*i}); } if(s>0) ve.push_back({v*s,w*s}); } /*for(int i=1;i<ve.size();i++){ for(int j=0;j<=m;j++){ if(j>=ve[i].v) f[i][j] = max(f[i-1][j],f[i-1][j-ve[i].v]+ve[i].w); else f[i][j] = f[i-1][j]; } }*/ for(auto it:ve) for(int i=m;i>=1;i--){ if(i>=it.v) f[i] = max(f[i-it.v]+it.w,f[i]); } cout<<f[m]<<endl; }