码迷,mamicode.com
首页 > 其他好文 > 详细

背包九讲之一

时间:2015-02-07 13:05:39      阅读:152      评论:0      收藏:0      [点我收藏+]

标签:

  1 /*
  2 有n个物品和一个容量为V的背包,第i件物品的费用是c[i],价值是w[i]
  3 求解哪些物品装入背包使价值总和最大
  4 dp[i][j]  dp[i][j] 为前i件物品放进容量为j的背包的最大价值
  5 dp[i][j] = max(dp[i-1][j],dp[i-1][j-c[i]]+w[i]);
  6 */
  7 #include <stdio.h>
  8 #include <string.h>
  9 int dp[111][1111];
 10 int dp2[1001];
 11 int c[111],w[111];
 12 bool flag[111];
 13 inline int max(const int &a, const int &b)
 14 {
 15     return a < b ? b : a;
 16 }
 17 int main()
 18 {
 19     int n,v,i,j;
 20     while(scanf("%d%d",&n,&v)!=EOF)
 21     {
 22         memset(dp,0,sizeof(dp));
 23         dp2[0] = 0;
 24         for(i=1; i<=n; ++i)
 25             dp2[i] = 1<<30;
 26         memset(flag,false,sizeof(flag));
 27         for(i=1; i<=n; ++i)
 28             scanf("%d",&w[i]);
 29         for(i=1; i<=n; ++i)
 30             scanf("%d",&c[i]);
 31         for(i=1; i<=n; ++i)//时间空间复杂度均为O(VN)
 32             for(j=0; j<=v; ++j)
 33             {
 34                 dp[i][j] = dp[i-1][j];
 35                 if(j>=c[i])
 36                     dp[i][j] = max(dp[i][j],dp[i-1][j-c[i]]+w[i]);
 37             }
 38         for(i=1; i<=n; ++i)
 39         for(j=v; j>=0; --j)
 40         {
 41             if(j>=c[i])
 42                 dp2[j] = max(dp2[j],dp2[j-c[i]]+w[i]);
 43         }
 44         printf("%d\n",dp[n][v]);
 45         printf("%d\n",dp2[v]);
 46         /*时间复杂度不能优化了,但是空间可以优化到O(V)
 47         for(i=1; i<=n; ++i)
 48         for(j=v; j>=0; --j)//将循环改为这样也是成立的
 49         那么每一个dp[i][j] 都是继承自上一层的dp[i-1][j] 或者dp[i-1][j-c[i]]
 50         那么j是大于等于j或者j-c[i]的。
 51         那么就可以这样
 52         for(i=1; i<=n; ++i)
 53         for(j=v; j>=c[i]; --j)//必须是从后忘前
 54         {
 55             dp2[j] = max(dp2[j],dp[j-c[i]+w[i]]);//这一层继承继承自上一层,这种数组叫做滚动数组
 56         }
 57         */
 58         //下面是判断哪几个背包被选
 59         int Max = dp[n][v];
 60         for(i=n; i>=1; --i)
 61         {
 62             if(dp[i-1][v]>= Max)
 63                 flag[i] = false;
 64             else
 65             {
 66                 flag[i] = true;
 67                 v -= c[i];
 68                 Max -= w[i];
 69             }
 70         }
 71         if(flag[1])
 72                 printf("1");
 73             else
 74                 printf("0");
 75         for(i=2; i<=n; ++i)
 76             if(flag[i])
 77                 printf(" 1");
 78             else
 79                 printf(" 0");
 80         printf("\n");
 81     }
 82     return 0;
 83 }
 84 /*
 85 5 10
 86 6 3 5 4 6
 87 2 2 6 5 4
 88 Sample Output:
 89 15
 90 1 1 0 0 1
 91 */
 92 /*
 93 另外还有就是求背包的最优解过程中,有两种要求:
 94 (1)要求背包装满,且价值最大(所以可能导致无解的情况发生)
 95 (2)只要求价值最大
 96 这两种问法差别在于初始化
 97 (1)将dp[0][0]初始化为0,其他的初始化为-INF,这是由题目的性质导致的
 98     初始的时候什么都不装,但是背包有容量而没装满是不合法的,所以定义-INF为不合法的
 99     如果要求背包装满,那么dp[i][j]表示的含义就变为了前i个物品装满容量为j的背包的最大价值
100     dp[i][j] = max(dp[i-1][j],dp[i-1][j-c[i]]+w[i]);
101     如果dp[i-1][j],dp[i-1][j-c[i]]+w[i] ,这两个状态是不合法的,那么dp[i][j]也是不合法的
102 (2)都初始化为0
103         
104 */

 

背包九讲之一

标签:

原文地址:http://www.cnblogs.com/justPassBy/p/4278581.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!