1 #include<cstdio> 2 #include<cmath> 3 #include<iostream> 4 #include<cstring> 5 const int qq=2000+50; 6 int v[qq],w[qq],dp[qq]; 7 using namespace std; 8 int main() 9 { 10 int t; 11 scanf("%d",&t); 12 while(t--){ 13 int n,m; 14 scanf("%d %d",&n,&m); 15 memset(dp,0,sizeof(dp)); 16 memset(v,0,sizeof(v)); 17 memset(w,0,sizeof(w)); 18 int count=1; 19 for(int i=0;i<m;++i){ 20 int value,weight,tot; 21 scanf("%d %d %d",&value,&weight,&tot); 22 int t=1; 23 while(tot>=t){ 24 v[count]=t*value; 25 w[count++]=t*weight; 26 tot-=t; 27 t<<=1; 28 } 29 if(tot){ 30 v[count]=tot*value; 31 w[count++]=tot*weight; 32 } 33 } 34 for(int i=1;i<count;++i) 35 for(int j=n;j>=v[i];--j) //j必须从n开始dp,如果循序开始dp的话v[i]会被取多次 36 dp[j]=max(dp[j],dp[j-v[i]]+w[i]); //也就是说达不到01背包要求的v[i]只有取和不取两种状态、 37 printf("%d\n",dp[n]); 38 } 39 }
算法时间复杂度O(V*∑log n[i])
总算是理解了为什么要逆序dp
#include <stdio.h> 02.#include <string.h> 03.#include <algorithm> 04.using namespace std; 05.int main() 06.{ 07. int ncase,p[105],w[105],c[105],dp[105]; 08. scanf("%d",&ncase); 09. while(ncase--) 10. { 11. int n,m,count=0; 12. scanf("%d %d",&n,&m); 13. for(int i=0;i<m;i++) 14. scanf("%d %d %d",&p[i],&w[i],&c[i]); 15. memset(dp,0,sizeof(dp)); 16. int temp=0; 17. for(int i=0;i<m;i++) 18. { 19. for(int j=n;j>=p[i];j--)//唉在这里又错了几次 要倒着来。 20. { 21. for(int k=1;k<=c[i];k++) 22. { 23. if(j<k*p[i]) break; 24. dp[j]=max(dp[j-k*p[i]]+k*w[i],dp[j]); 25. if(dp[j]>temp) 26. temp=dp[j]; 27. } 28. } 29. } 30. printf("%d\n",temp); 31. } 32. return 0; 33.}
上述代码是借鉴别人的、 也是多重背包最原始的解法
时间复杂度O(V*∑n[i])
原文:http://www.cnblogs.com/sasuke-/p/5240139.html