题目:
正文:
-
啊,多重背包真恶心。。。
-
一开始我是把多重背包改成了01背包,然鹅我当时是直接1个1个的往后摞的。。。
-
参见以下代码:
-
for(int i=1;i<=n;++i){//平平无奇的输入 v[i]=R;w[i]=R;num[i]=R; } for(int i=1;i<=t;++i){//t等于n,但是一会要修改n,所以使用了另一个变量 while(--num[i]){//把--提前是因为下标i这里还需要留1个 v[++n]=v[i];//摞摞摞 w[n]=w[i]; } }
-
于是数据就很多,然后就TLE了。。。
(实测:50分(开O2) | 30分(不开O2)) -
然后按照背包九讲里面的板子改了改贴上去A惹,但是我到现在还没有看懂那个板子每一句话的意思。。。
-
于是我又按照最开始的思路开始了我的修改之旅,正是:
-
一改一改又一改,改完是错还超时。
-
不知不觉秃顶中,但愿评测能AC。
-
我借鉴了那个背包九讲里面用次方求解的思路,把1个1个摞改成了几个几个往后摞。。。
-
如下:
-
for(int i=1;i<=n;++i){ a=R;b=R;c=R;//代替输入,因为不这样的话会很麻烦 for(int j=1;j<=c;j<<=1){//j是摞的个数 v[++t]=a*j;//摞 w[t]=b*j; c-=j;//去掉摞上的个数 } if(c){//因为c可能会有剩余,所以特判一下 v[++t]=a*c; w[t]=b*c; } }
-
这样就A啦啦啦。
Code:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <list>
using namespace std;
#define R read()
#define GC getchar()
#define ll long long
#define ull unsigned long long
#define INF 0x7fffffff
#define LLINF 0x7fffffffffffffff
ll read(){
ll s=0,f=1;
char c=GC;
while(c<'0'||c>'9'){if(c=='-')f=-f;c=GC;}
while(c>='0'&&c<='9'){s=s*10+c-'0';c=GC;}
return s*f;
}
int n,m,t;
int a,b,c;
int v[200010],w[200010];
int f[40010];
int main(){
n=R;m=R;
for(int i=1;i<=n;++i){
a=R;b=R;c=R;//代替输入,因为不这样的话会很麻烦
for(int j=1;j<=c;j<<=1){//j是摞的个数
v[++t]=a*j;//摞
w[t]=b*j;
c-=j;//去掉摞上的个数
}
if(c){//因为c可能会有剩余,所以特判一下
v[++t]=a*c;
w[t]=b*c;
}
}
for(int i=1;i<=t;++i){//平平无奇的01背包
for(int j=m;j>=w[i];--j){
f[j]=max(f[j],f[j-w[i]]+v[i]);
}
}
printf("%d",f[m]);//输出
return 0;
}