背包

来源:互联网 发布:魔力怀旧宠物满档数据 编辑:程序博客网 时间:2024/04/29 17:57
@JintianGo 2014-11-08 10:44 字数 2396 阅读 1

模板

背包

    • 背包
      • 一.01背包:(每种背包零或一)
      • 二.完全背包:(每种数量不限)
      • 三.多重背包:(每种背包数量给出)
      • 四.完整程序
      • 五.例题
        • 1(POJ1276)
        • 2(UVA12653)

一.01背包:(每种背包零或一)

  1. int v; //v为总的容量
  2. int dp[N];
  3. void ZeroOnePack(int cost,int weight){
  4. for(int j=v;j>=cost;j--) ///注意是逆序的(滚动数组)
  5. dp[j]=max(dp[j],dp[j-cost]+weight);
  6. }

二.完全背包:(每种数量不限)

  1. int v; //v为总的容量
  2. int dp[N];
  3. void CompletePack(int cost,int weight){
  4. for(int j=cost;j<=v;j++) ///注意是顺序的
  5. dp[j]=max(dp[j],dp[j-cost]+weight);
  6. }

三.多重背包:(每种背包数量给出)

何谓多重背包,就是在原来经典的0/1背包的基础上规定一个物品可以背有限次,也是区别于无限背包的特点之一。其实解决的方法很简单,只要把一个物品的多次看做是另一个物品,也就是说产生一种新的物品这个物品的重量是原来的两倍,三倍,…n倍。这样就将多重背包转化成了典型的0/1背包了.

  1. int v; //v为总的容量
  2. int dp[N];
  3. void MultiplePack(int cost,int weight,int amount){
  4. if(cost*amount>=v)
  5. CompletePack(cost,weight);
  6. else
  7. {
  8. int k=1;
  9. while(k<amount)
  10. {
  11. ZeroOnePack(k*cost,k*weight);
  12. amount-=k;
  13. k+=k;
  14. }
  15. ZeroOnePack(amount*cost,amount*weight);
  16. }
  17. }

四.完整程序

  1. void ZeroOnePack(int cost,int weight)
  2. {
  3. for(int j=v; j>=cost; j--) ///注意是逆序的
  4. dp[j]=max(dp[j],dp[j-cost]+weight);
  5. }
  6. void CompletePack(int cost,int weight)
  7. {
  8. for(int j=cost; j<=v; j++) ///注意是顺序的
  9. dp[j]=max(dp[j],dp[j-cost]+weight);
  10. }
  11. void MultiplePack(int cost,int weight,int amount)
  12. {
  13. if(cost*amount>=v)
  14. CompletePack(cost,weight);
  15. else
  16. {
  17. int k=1;
  18. while(k<amount)
  19. {
  20. ZeroOnePack(k*cost,k*weight);
  21. amount-=k;
  22. k+=k;
  23. }
  24. ZeroOnePack(amount*cost,amount*weight);
  25. }
  26. }

五.例题

1(POJ1276)

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <string>
  5. #include <stack>
  6. #define maxn 100000+10
  7. using namespace std;
  8. int v,N;
  9. int cnt[11],c[1001];
  10. int dp[maxn];
  11. void ZeroOnePack(int cost,int weight)
  12. {
  13. for(int j=v; j>=cost; j--) ///注意是逆序的
  14. dp[j]=max(dp[j],dp[j-cost]+weight);
  15. }
  16. void CompletePack(int cost,int weight)
  17. {
  18. for(int j=cost; j<=v; j++) ///注意是顺序的
  19. dp[j]=max(dp[j],dp[j-cost]+weight);
  20. }
  21. void MultiplePack(int cost,int weight,int amount)
  22. {
  23. if(cost*amount>=v)
  24. CompletePack(cost,weight);
  25. else
  26. {
  27. int k=1;
  28. while(k<amount)
  29. {
  30. ZeroOnePack(k*cost,k*weight);
  31. amount-=k;
  32. k+=k;
  33. }
  34. ZeroOnePack(amount*cost,amount*weight);
  35. }
  36. }
  37. int main()
  38. {
  39. while(~scanf("%d%d",&v,&N))
  40. {
  41. for(int i=0; i<N; i++)
  42. cin>>cnt[i]>>c[i];
  43. memset(dp,0,sizeof(dp));
  44. for(int i=0; i<N; i++)
  45. MultiplePack(c[i],c[i],cnt[i]);//注意这里要考虑到起点的cost与weight都是c[i]
  46. cout<<dp[v]<<endl;
  47. }
  48. return 0;
  49. }

2(UVA12653)

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. #define maxn 10000
  5. using namespace std;
  6. int a[55];
  7. int dp[maxn];
  8. int main()
  9. {
  10. int T,n,t;
  11. cin>>T;
  12. int tmp=T;
  13. while(T--)
  14. {
  15. cin>>n>>t;
  16. memset(dp,-1,sizeof(dp));
  17. dp[0]=0;
  18. for(int i=0;i<n;i++)
  19. {
  20. cin>>a[i];
  21. for(int j=t-1;j>=a[i];j--)
  22. if(~dp[j-a[i]])//一个小优化
  23. dp[j]=max(dp[j],dp[j-a[i]]+1);
  24. }
  25. int ans=0,index=0;
  26. for(int j=t-1;j>=0;j--)
  27. {
  28. if(dp[j]>ans)
  29. {
  30. ans=dp[j];
  31. index=j;
  32. }
  33. }
  34. printf("Case %d: %d %d\n",tmp-T,ans+1,index+678);
  35. }
  36. }
@JintianGo 2014-11-08 10:44 字数 2396 阅读 1
正在加载文章图片,请稍等片刻...
0 0
原创粉丝点击