1/*0-1背包递归*/
2#include<iostream>
2 #include <iomanip>
3 using namespace std;
4
5 int w[]={1,3,4,5};//物品重量数组
6 int v[]={2,30,44,20};//物品价值数组
7 int contain=5;//背包容量
8 int y[4]={-1,-1,-1,-1};//解向量,y[i]=1表示选取物品,y[i]=0表示不选取物品
9
10 int f(int n,int contain)
11 {
12 if(n==0 || contain==0){//当物品数量为0,或者背包容量为0时,最优解为0
13 return 0;
14 }
15 else
16 {
17 //从当前所剩物品的最后一个物品开始向前,逐个判断是否要添加到背包中
18 for(int i=n-1;i>=0;i--){
19 //如果当前要判断的物品重量大于背包当前所剩的容量,那么就不选择这个物
20 //在这种情况的最优解为f(n-1,C)
21 if(w[i]>contain){
22 y[i]=0;
23 return f(n-1,contain);
24 }
25 else
26 {
27 //如果当前待判断的物品重量wi<C,那么就选取f(n-1,C)和vi+f(n-1,C-wi)中的最大值
28 int tmp1=f(n-1,contain);//不选择物品i的情况下的最优解
29 int tmp2=v[i]+f(n-1,contain-w[i]);//选择物品i的情况下的最优解
30 //返回选择物品i和不选择物品i中最优解大的一个
31 if(tmp1>tmp2){
32 y[i]=0;//这种情况下表示物品i未被选取
33 return tmp1;
34 }
35 else
36 {
37 y[i]=1;//物品i被选取
38 return tmp2;
39 }
40 }
41 }
42 }
43 }
44 int main()
45 {
46 int maxvalue=f(4,5);
47 for(int i=0;i<4;i++){
48 if(y[i]==1)
49 {
50 cout<<"Object"<<i+1<<"is selected"<<"It's value is"<<setw(2)<<
51 v[i]<<"It's Weight is"<<setw(2)<<w[i]<<endl;
52 }
53 }
54 cout<<"Maximum Value is"<<maxvalue<<endl;
55 return 0;
56
57 }
1 /* 0-1背包非递归*/
2 #include "stdio.h"
3 #define N 100
4
5 int main()
6 {
7 void Knapsack(int [],int [],int ,int ,int [][1000]);
8 void Traceback(int [],int [],int ,int ,int [][1000],int []);
9 int n,i,c,v[N+1],w[N+1],m[N+1][1000],x[N+1];
10 //v[]:价值,w[]:重量,c:背包可容纳重量,n:物品件数
11 //m[][]:存放最大总价值的数组
12 //m[i][j]表示背包容量为j,可选择物品为i,i+1,...,n时0-1背包问题的最优值
13 //x[i]表示是否放入第i件物品,1为是,0为否
14 printf("input n:");
15 scanf("%d",&n);
16 printf("input c:");
17 scanf("%d",&c);
18 printf("input v:");
19 for(i=1;i<=n;i++) scanf("%d",&v[i]);
20 printf("input w:");
21 for(i=1;i<=n;i++) scanf("%d",&w[i]);
22 Knapsack(v,w,c,n,m);
23 Traceback(v,w,c,n,m,x);
24 printf("answer:%d\n",m[1][c]);
25 for(i=1;i<=n;i++)
26 if(x[i]) printf("%d ",i);
27 printf("\n");
28
29 return 0;
30 }
31
32 void Knapsack(int v[],int w[],int c,int n,int m[][1000])
33 //v[]:价值,w[]:重量,c:背包可容纳重量,n:物品件数
34 //m[][]:存放最大总价值的数组
35 //m[i][j]表示背包容量为j,可选择物品为i,i+1,...,n时0-1背包问题的最优值
36 {
37 int i,j,t;
38 int jMax;
39 jMax=w[n]-1<=c? w[n]-1:c;
40 //jMax是使m[n][x]为0的x最后下标
41 for(j=0;j<=jMax;j++) m[n][j]=0;
42 //对于背包容量k(0<=k<=jMax),物品n是超重的,故在这些容量下,一定不会选择物品n
43 //故(m[n][0],m[n][1],...m[n][jMax-1],m[n][jMax]) = 0
44 for(j=w[n];j<=c;j++) m[n][j]=v[n];
45 //对于背包容量k(w[n]<=k<=c),物品n是可容纳的,故在这些容量下,选择物品n
46 //以下是前面两个for循环的实例:
47 //例1:n=6,w[6]=9,c=12,则(m[6][0],m[6][1],m[6][2],...m[6][7],m[6][8])=0
48 // (m[6][9],...m[6][12]=v[6]
49 //例2:n=6,w[6]=9,c=8,则(m[6][0],m[6][1],m[6][2],...m[6][8],m[6][9])=0
50
51 //到此为止,已经求出可选择物品只有第n件时在重量k(0<=k<=c)情况下的最优值
52 //接下来求可选择物品为(第n-1件、第n件),(第n-2件、第n-1件、第n件),...,(第2件、第3件...第n件) 在重量k(0<=k<=c)情况下的最优值
53 for(i=n-1;i>1;i--)
54 {
55 jMax=w[i]-1<=c? w[i]-1:c;
56 //jMax是使m[i][x]为0的x最后下标
57 for(j=1;j<=jMax;j++) m[i][j]=m[i+1][j];
58 //对于背包容量k(0<=k<=jMax),物品i是超重的,在这些容量下,一定不会选择物品i
59 //即(m[i][1]=m[i+1][1],m[i][2]=m[i+1][2],...,m[i][jMax]=m[i+1][jMax];
60 for(j=w[i];j<=c;j++)
61 {
62 //对于背包容量k(w[i]<=k<=c),物品i是可容纳的,但是否一定选择物品i?
63 t=w[i];
64 m[i][j]=m[i+1][j]>=m[i+1][j-t]+v[i]?m[i+1][j]:m[i+1][j-t]+v[i];
65 //以上语句你能看明白,这是0-1背包模型的关键
66 }
67 //到此为止,已经求出可选择物品为(第n-1件、第n件),(第 n-2件、第n-1件、第 n件),...,(第 2件、第 3件...第 n 件) 在重量 k(0<=k<=c)情况下的最优值
68 //接下来是求可选择物品为(第 1件、第 2件...第 n件) 在重量 k(0<=k<=c)情况下的最优值吗?
69 //No!只需求可选择物品为(第 1件、第 2件...第 n件) 在重量 c(真正的背包容量)下的最优值
70 m[1][c]=m[2][c]; //假设不放入第一件物品
71 t=w[1];
72 if(w[1]<=c) m[1][c]=m[1][c]>=m[2][c-t]+v[1]?m[1][c]:m[2][c-t]+v[1];
73 //可以容纳第一件物品的情况下,该如何选择?
74 }
75 }
76
77 void Traceback(int v[],int w[],int c,int n,int m[][1000],int x[])
78 {
79 //v[]:价值,w[]:重量,c:背包可容纳重量,n:物品件数
80 //m[][]:存放最大总价值的数组
81 //m[i][j]表示背包容量为j,可选择物品为i,i+1,...,n时0-1背包问题的最优值
82 //x[i]表示是否放入第i件物品,1为是,0为否
83 int i;
84 for(i=1;i<n;i++)
85 if(m[i][c]==m[i+1][c]) x[i]=0;
86 //可选择物品中有第i件物品或没有第i件物品,最优值都是一样的,故一定没有放入第 i件物品
87 else
88 {
89 x[i]=1;
90 c=c-w[i];
91 //这个语句很重要,为判断是否选择了第 i+1件物品做准备
92 }
93 if(m[n][c]>0) //单独判断是否选择了第 n件物品
94 x[i]=1;
95 else x[i]=0;
96 }