0-1背包问题
2 2 6 5 4
6 3 5 4 6
C[i][j]=max{C[i-1][j],C[i-1][j-wi]+vi} j>=wi这一步就是考虑将该物品可以装入的情况下,是否可以是一定质量下价值最大 就是判断在抉择某一物品时,重量从0到W的最佳抉择方案
或者
C[i][j]=C[i-1][j] j<wi因为达不到那个重量,所以不可能装入该物品,所以此物品没有被装入
以上这个公式非常重要,要是通过这个公式理解了挑选物品的规划过程,0-1背包问题就理解了。
当i从1开始到n-1的过程中,不断的探索C[i][j](0<=j<=W)的值,选出一个最优值。
当j从0到W的变化过程中,探索不同重量能获得的价值。
我觉得最妙的地方在于,它会从该物品放入或者没有放入两种情况中选择一种最优值放入。
0 1 2 3 4 5 6 7 8 9 10 |
0 0 0 0 0 0 0 0 0 0 0 0 1 2 3 4 5 |
#include <iostream>
using namespace std;
struct Weight_Value{
int weight;
int value;
};
int n;
int W;
int *Weight;
int *Value;
Weight_Value *p;
int point;
void function_0_1(){
p=new Weight_Value[1000];
Weight_Value *q=new Weight_Value[1000];
Weight_Value *tempArr=new Weight_Value[1000];
int p_next=1;
int q_next=1;
p[0].weight=0;
p[0].value=0;
for(int i=0;i<n;i++){
point=0;
for(int j=0;j<=p_next-1;j++){
tempArr[j].weight=p[j].weight;
tempArr[j].value=p[j].value;
}
for(int j=0,k=0;j<=q_next-1;){//对q[i]进行处理
if(p[j].weight+Weight[i]>W){
q_next--;
continue;
}
q[j].weight=p[j].weight+Weight[i];
q[j].value=p[j].value+Value[i];
j++;
}
for(int j=0,k=0;j<=p_next-1||k<=q_next-1;){//求p[i]和q[i]的并集
if(j<=p_next-1&&tempArr[j].weight<=q[k].weight){
if(tempArr[j].weight==q[k].weight&&tempArr[j].value<q[k].value){
p[point].weight=q[k].weight;
p[point++].value=q[k++].value;
continue;
}
p[point].weight=tempArr[j].weight;
p[point++].value=tempArr[j++].value;
}
else if(k<=q_next-1&&q[k].value>tempArr[j-1].value){
while(j<=p_next-1&&q[k].value>tempArr[j].value)j++;
p[point].weight=q[k].weight;
p[point++].value=q[k++].value;
}
else if(k>q_next-1){
if(tempArr[j].weight>=q[k-1].weight&&tempArr[j].value>q[k-1].value){
p[point].weight=tempArr[j].weight;
p[point++].value=tempArr[j++].value;
}
else j++;
}
else k++;
}
p_next=point;
q_next=point;
}
}
int main()
{
//cout<<"请输入容量:"<<endl;
cin>>W;
//cout<<"请输入物品个数:"<<endl;
cin>>n;
Value=new int[n];
Weight=new int[n];
for(int i=0;i<n;i++){
//cout<<"请输入第"<<i+1<<"物品的质量和重量:"<<endl;
cin>>Weight[i]>>Value[i];
}
function_0_1();
cout<<"以下是对p进行输出:"<<endl;
cout<<"point="<<point<<endl;
for(int i=0;i<point;i++)cout<<p[i].weight<<" "<<p[i].value<<endl;
return 0;
}
测试如下数据通过:
1000 100
88 53
85 70
59 20
100 41
94 12
64 71
79 37
75 87
18 51
38 64
47 63
11 50
56 73
12 83
96 75
54 60
23 96
6 70
19 76
31 25
30 27
32 89
21 93
31 40
4 41
30 89
3 93
12 46
21 16
60 4
42 41
42 29
78 99
6 82
72 42
25 14
96 69
21 75
77 20
36 20
42 56
20 23
7 92
46 71
19 70
24 1
95 63
3 18
93 11
73 68
62 33
91 6
100 82
58 69
57 78
3 48
32 95
5 42
57 53
50 99
3 15
88 76
67 64
97 39
24 48
37 83
41 21
36 75
98 49
52 73
75 85
7 28
57 31
23 86
55 63
93 12
4 71
17 35
5 21
13 17
46 73
48 18
28 7
24 51
70 94
85 88
48 46
48 77
55 80
93 95
6 31
8 80
12 32
50 45
95 5
66 30
92 51
25 63
80 43
16 9
结果:2852