有N 种物品,每种物品的数量为C1,C2......Cn。从中任选若干件放在容量为W的背包里,每种物品的体积为W1,W2......Wn(Wi为整数),与之相对应的价值为P1,P2......Pn(Pi 为整数)。求背包能够容纳的最大价值。
Input
第1 行,2 个整数,N 和W中间用空格隔开。N 为物品的种类,W为背包的容量。(1 <= N <= 100 ,1 <= W <= 50000 )
第2 - N + 1 行,每行3 个整数,Wi,Pi 和Ci分别是物品体积、价值和数量。(1 <= Wi, Pi <= 10000 , 1 <= Ci <= 200 )
Output
输出可以容纳的最大价值。
Input 示例
3 6
2 2 5
3 3 8
1 4 1
Output示例
9
典型的多重背包问题,可是我用的是01 背包的做法,记得之前也是这样子做。
这里就是把多重背包拆分成01 背包的做法。
我之前是1 ,1 ,1 ,1 ,1. ... 拆的,然后T 了。
所以呢,要对此进行优化一下。
怎么优化呢,我们可以根据二进制来拆分背包。
既拆分成1 ,2 ,4 ,8 ,....... ,( 1 <<(n-1 ) )
那么Ci怎么变化的,就是每一次拆分Ci- 1 <<(i+1 ),
最后还有对Ci进行讨论,如果不为0 ,需要再开一个空间存剩下的。
然后01 背包,dp[j]=max(dp[j],dp[j-w[i]]+v[i]).
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<ctime>
#include<string>
#include<stack>
#include<deque>
#include<queue>
#include<list>
#include<set>
#include<map>
#include<cstdio>
#include<limits.h>
#define MOD 1000000007
#define fir first
#define sec second
#define fin freopen("/home/ostreambaba/文档/input.txt", "r", stdin)
#define fout freopen("/home/ostreambaba/文档/output.txt", "w", stdout)
#define mes(x, m) memset(x, m, sizeof(x))
#define Pii pair<int, int>
#define Pll pair<ll, ll>
#define INF 1e9+7
#define Pi 4.0*atan(1.0)
#define lowbit(x) (x&(-x))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
typedef long long ll;
typedef unsigned long long ull;
const double eps = 1e-12 ;
const int maxn = 50010 ;
using namespace std ;
inline int read(){
int x(0 ),op(1 );
char ch=getchar();
while (ch<'0' ||ch>'9' ){if (ch=='-' )op=-1 ,ch=getchar();}
while (ch>='0' &&ch<='9' )x=x*10 +ch-'0' ,ch=getchar();
return x*op;
}
int main()
{
int N,W;
N=read(),W=read();
int c,w,p,k,j,re,tmp;
j=-1 ,k=0 ;
int n[maxn],m[maxn];
for (int i=0 ;i<N;++i){
c=read(),w=read(),p=read();
for (int l=1 ;l<=p;l<<=1 ){
n[++j]=c*l;
m[j]=w*l;
p-=l;
k++;
}
if (p!=0 ){
n[++j]=c*p;
m[j]=w*p;
k++;
}
}
int dp[maxn];
mes(dp,0 );
for (int i=0 ;i<k;++i){
for (j=W;j>=n[i];--j){
dp[j]=max(dp[j],dp[j-n[i]]+m[i]);
}
}
cout <<dp[W]<<endl;
return 0 ;
}