分析:这个和我们之前讲的0-1背包问题很像。
思路1:
思路1:
我们显然可以把每种物品的每一件都作为一个新的物品按照普通0-1背包的方法做。
但是0-1背包的时间复杂度是O(W * N) , 这里N = C1 + C2 + …+ Cn。
思路2:
但是0-1背包的时间复杂度是O(W * N) , 这里N = C1 + C2 + …+ Cn。
思路2:
换个角度我们用dp[i][j]表示前i件物品,总重量为j的时候的最大价值。
则dp[i][j] = max{dp[i – 1][j – k * Wi] + k * Vi}
其中 0 ≤ k ≤ min( j / Wi , Ci)
这个的时间复杂度是n * W * max(Ci)
则dp[i][j] = max{dp[i – 1][j – k * Wi] + k * Vi}
其中 0 ≤ k ≤ min( j / Wi , Ci)
这个的时间复杂度是n * W * max(Ci)
最后,我们来提供输入输出数据,由你来写一段程序,实现这个算法,只有写出了正确的程序,才能继续后面的课程。
输出示例
输入
第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)
输出
输出可以容纳的最大价值。
输入示例
3 6 2 2 5 3 3 8 1 4 1
输出示例
9
请选取你熟悉的语言,并在下面的代码框中完成你的程序,注意数据范围,最终结果会造成Int32溢出,这样会输出错误的答案。
1 line=input().split() 2 n=int(line[0]) 3 m=int(line[1]) 4 w=[] 5 p=[] 6 c=[] 7 for i in range(n): 8 line=input().split() 9 tw=int(line[0]) 10 tp=int(line[1]) 11 tc=int(line[2]) 12 k=1 13 while tc>=k: 14 w.append(k*tw) 15 p.append(k*tp) 16 tc-=k 17 k*=2 18 if tc>0: 19 w.append(tc*tw) 20 p.append(tc*tp) 21 n2=len(w) 22 f=[] 23 for i in range(m+1): 24 f.append(0) 25 for i in range(n2): 26 for j in range(m,w[i]-1,-1): 27 f[j]=max(f[j],f[j-w[i]]+p[i]) 28 print(f[m]) 29
又超时!!
1 #include<cstdio> 2 int max(int a,int b){ 3 if (a>b) return a; 4 else return b; 5 } 6 int main(){ 7 int n,m,c,tw,tp; 8 int w[1000],p[1000],f[50000]; 9 scanf("%d%d",&n,&m); 10 int j=-1; 11 for(int i=0;i<n;i++){ 12 scanf("%d%d%d",&tw,&tp,&c); 13 int k=1; 14 while (c>=k){ 15 j++; 16 w[j]=tw*k; 17 p[j]=tp*k; 18 c-=k; 19 k*=2; 20 } 21 if (c>0){ 22 j++; 23 w[j]=tw*c; 24 p[j]=tp*c; 25 } 26 } 27 int n2=j+1; 28 for(int i=0;i<=m;i++){ 29 f[i]=0; 30 } 31 for(int i=0;i<n2;i++){ 32 for(int j=m;j>=w[i];j--){ 33 f[j]=max(f[j],f[j-w[i]]+p[i]); 34 } 35 } 36 printf("%ld",f[m]); 37 return 0; 38 }