0-1背包问题

问题:

有N件物品和一个容量为V的背包。第i件物品的价值是c[i],重量是w[i]。求解将哪些物品装入背包可使这些物品的重量总和不超过背包容量,且价值总和最大。

这个问题的特点是:每种物品只有一件,可以选择放或者不放。用f[i][j]表示背包当前容量为j,选择装入1-i个物品时的最大价值

在求最优解的背包问题中,一般有两种不同的问法:1、求小于等于背包容量的最优解,即不一定恰好装满背包;2、要求“恰好装满背包”时的最优解.

1、求小于等于背包容量的最优解,即不一定恰好装满背包;

设f[0..N][0..v]=0

2、要求“恰好装满背包”时的最优解.

则f[0][1..v]=-∞,确保当背包不满时得不到最优解(价值最大)

状态转移方程:

  1. f[i][j]=f[i-1][j]         j<w[i-1]
  2. f[i][j]=max{f[i-1][j].f[i-1][j-w[i-1]]+c[i-1]}        其它

解释:

1.背包当前容量j小于第i件物品的重量w[i-1],第i件物品装不下,所有不放第i件物品

2.第i件物品可以放下,进行选择,放或者不放

  • 如果不放,则问题转化为“前i-1件物品放入容量为j的背包中”
  • 如果放,则问题转化为“前i-1件物品放入剩下的容量为j-w[i-1]的背包中”,此时能获得的最大的价值就是f[i-1][j-w[i-1]]再加上通过放入第i件物品获得的价值c[i-1]

在“其它”情况下,f[i][j]的值就是上述两种情况中的最大值

代码:

 1 #include<iostream>
 2 using namespace std;
 3 int f[100][100];
 4 int Min=-999999;
 5 int package(int n,int v,int w[],int c[])    //n-物品数量,v-背包容量,w[]各个物品的重量,c[]对应物品的价值
 6 {
 7     if(f[n][v]!=0)                    //已计算过该子问题
 8         return f[n][v];
 9     if(n==0||v<=0)      //题型一:价值最大,不要求装满
10         return 0;
11 
12     //if(n==0)    //题型二:背包装满的情况下最大价值,设f[0][0]=0,f[0][1..v]=-∞,即当背包不满时没有最优解
13     //{
14     //    if(v!=0) return Min;
15     //    return 0;
16     //}
17 
18     if(v<w[n-1])           //第n件物品的重量大于当前背包的容量,则不装第n件物品,背包容量仍为v,从剩余的n-1件物品中选择
19         f[n][v]=package(n-1,v,w,c);
20     else               //背包当前容量可以装下第n件物品,可以选择装或者不装第n件物品
21     {
22         int a=package(n-1,v,w,c);      //不装第n件物品,从剩余的n-1件物品中选择,背包容量仍为v
23         int b=package(n-1,v-w[n-1],w,c)+c[n-1];   //装第n件物品,则当前价值为第n件物品的价值c[n]加上(n-1,v-w[n])问题的最优解
24         f[n][v]=a>b?a:b;            //选择价值最大的解
25     }
26     return f[n][v];
27 }
28 
29 int main()
30 {
31     memset(f,0,sizeof(f));    //设置边界条件
32     int n,v,w[100],c[100];
33     cout<<"input the number of items:";
34     cin>>n;
35     cout<<"input the volume of items:";
36     cin>>v;
37     cout<<"input the weight of items:";
38     for(int i=0;i<n;i++)
39         cin>>w[i];
40     cout<<"input the value of items:";
41     for(int i=0;i<n;i++)
42         cin>>c[i];
43     cout<<"the bigest value is:";
44     cout<<package(n,v,w,c)<<endl;
45 }
View Code

结果:

问法一:求小于等于背包容量的最优解,即不一定恰好装满背包;

问法二:要求“恰好装满背包”时的最优解.

posted on 2016-05-06 19:18  小菜鸡y  阅读(302)  评论(0编辑  收藏  举报