0-1背包的动态规划,回溯,分支限界三种解法1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int Traceback(int **map, int n, int *X, int Max_Weight, int *Weight);
int Knaspack(int *Weight, int * Value, int Max_Weight, int n, int **map);
int max(int m,int n);
int min(int m,int n);
int main()
{
int i;
int Weight[] = {0,2,2,6,5,4}; //一维数组,存有每个物品的重量,Weight[0]存为0,无实际意义。
int Value[] = {0,6,3,5,4,6}; //一维数组,存有每个物品的价值,同上。
int Max_Weight = 10; //背包所能放的最大重量。
int n = sizeof(Weight) / sizeof(Weight[0]) - 1; //n:物品的个数。
int **map =(int **)malloc(sizeof(int *) * (n + 1)); //二维数组map作为地图,行数为n+1,列数为Max_Weight+1;
for(i = 0;i < n + 1;i++){
map[i] = (int *)malloc(sizeof(int) * (Max_Weight + 1));
}
int *X = (int *)malloc(sizeof(int) * (n + 1)); //一维数组X存储结果
Knaspack(Weight, Value, Max_Weight, n, map); //填表
Traceback(map, n, X, Max_Weight, Weight); //由表得出结果
for(i = 1; i <= n; i++){
printf("第%d个:%2d\n", i, X[i]); //打印结果
}
printf("%d\n",map[1][Max_Weight]);
return 0;
}
int Knaspack(int *Weight, int * Value, int Max_Weight, int n, int **map)
{
int i,j;
int jMax = min(Weight[n] - 1,Max_Weight); //先开始填表的最后一行,即:先开始考虑第n个物品拿不拿。此处,选取两者中的最小为拿不拿第n个物品的分界点。
for(j = 0; j <= jMax; j++){ //此处为不能拿第n个物品时,所得的价值为0.
map[n][j] = 0;
}
for(j = Weight[n]; j < Max_Weight; j++){ //此处为拿第n个物品时,所得价值为Vanlue[n];
map[n][j] = Value[n];
}
for(i = n - 1; i > 1; i--){
jMax = min(Weight[i] - 1, Max_Weight); //能不能拿第i个物体的分界
for(j = 0; j <= jMax; j++){
map[i][j] = map[i+1][j]; //不能拿时所得价值维持不变
}
for(j = Weight[i]; j <= Max_Weight; j++){
map[i][j] = max(map[i + 1][j], map[i + 1][j - Weight[i]] + Value[i]); //比较两者,前者为选择不拿此物品所能得的价值,后者为拿此物品所得的价值,相比较取最大。
}
}
map[1][Max_Weight] = map[2][Max_Weight];
if(Max_Weight >= Weight[1]){
map[1][Max_Weight] = max(map[1][Max_Weight],map[2][Max_Weight - Weight[1]] + Value[1]);
}
}
int max(int m,int n)
{
if(m < n){
return n;
}else{
return m;
}
}
int min(int m,int n)
{
if(m < n){
return m;
}else{
return n;
}
}
int Traceback(int **map, int n, int *X, int Max_Weight, int *Weight)
{
int i;
for(i = 1; i < n; i++){
if(map[i][Max_Weight] == map[i + 1][Max_Weight]){ //如果这两个数相等则说明没有拿此物品
X[i] = 0;
}
else{
X[i] = 1;
Max_Weight -= Weight[i];
}
}
X[n] = (map[n][Max_Weight])? 1 : 0;
}
1 | #include<iostream> |