forked from cxl98/interview
-
Notifications
You must be signed in to change notification settings - Fork 1
/
pack.cpp
170 lines (145 loc) · 3.62 KB
/
pack.cpp
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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#include <iostream>
#include <algorithm>
using namespace std;
int **T = NULL; // 存储背包问题表格的数组指针
// 返回两个值的最大值
int max(int a, int b) {
return (a > b) ? a : b;
}
// 迭代法,能显示背包问题的表格
int packIterative(int n, int W, int *w, int *v) {
// 循环遍历n行
for (int i = 1; i <= n; ++i)
{
// 循环遍历W列
for (int j = 1; j <= W; ++j)
{
//第i个物品能装下,则比较包括第i个物品和不包括第i个物品,取其最大值
if (w[i] <= j)
T[i][j] = max(v[i] + T[i - 1][j - w[i]], T[i - 1][j]);
// 第i个物品不能装下,则递归装i-1个
else
T[i][j] = T[i - 1][j];
}
}
return T[n][W];
}
// 递归法,不支持显示背包问题的表格
int packRecursive(int n, int W, int *w, int *v) {
// 结束条件(初始条件),i或者j为0时最大总价值为0
if (n == 0 || W == 0) {
return 0;
}
// 第i个物品不能装下,则递归装i-1个
if (w[n] > W) {
return packRecursive(n - 1, W, w, v);
}
//第i个物品能装下,则比较包括第i个物品和不包括第i个物品,取其最大值
else {
return max(v[n] + packRecursive(n - 1, W - w[n], w, v), packRecursive(n - 1, W, w, v));
}
}
// 打印背包问题的表格
void printT(int n, int W)
{
// 打印n行
for (auto i = 0; i <= n; i++)
{
// 打印行数
cout << i << ":\t";
// 打印W列
for (int w = 0; w <= W; w++)
{
cout << T[i][w] << "\t";
}
// 换行
cout << endl;
}
}
int main() {
int *w = NULL; // 存储每件物品重量的数组指针
int *v = NULL; // 存储每件物品价值的数组指针
int n; // 物品个数n
int W; // 背包总承重W
cout << "---------------- 背包问题 ----------------" << endl;
cout << "请输入物品数 n (n>=0) " << endl;
// 输入背包数
cin >> n;
if (cin.fail() || n < 0)
{
cout << "输入n错误!" << endl;
system("pause");
return 0;
}
cout << "请输入背包承重量 W (W>=0) " << endl;
// 输入背包承重量
cin >> W;
if (cin.fail() || W < 0)
{
cout << "输入W错误!" << endl;
system("pause");
return 0;
}
// 分配空间
// 对w和v分配n+1大小
w = new int[n + 1];
v = new int[n + 1];
// 对T分配n+1行,并初始化为0
T = new int *[n + 1]();
// 对T分配W+1列,并初始化为0
for (auto i = 0; i <= n; i++)
{
T[i] = new int[W + 1]();
}
// 输入背包的重量和价值
for (auto i = 1; i <= n; i++)
{
cout << "请输入第 " << i << " 个物品的重量和价值(用空格隔开)" << endl;
cin >> w[i] >> v[i];
if (cin.fail() || w[i] < 0 || v[i] < 0)
{
cout << "输入错误!" << endl;
system("pause");
return 0;
}
}
cout << "------------------------------------------------" << endl;
cout << "请选择算法:" << endl;
cout << "【1】迭代法" << endl;
cout << "【2】递归法" << endl;
cout << "------------------------------------------------" << endl;
int choose;
// 输入算法的选择
cin >> choose;
switch (choose)
{
case 1:
{
// 迭代法,能显示背包问题的表格
cout << "能装下物品的最大价值为 " << packIterative(n, W, w, v) << endl;
cout << "------------------------------------------------" << endl;
printT(n, W);
break;
}
case 2:
{
// 递归法,不支持显示背包问题的表格
cout << "能装下物品的最大价值为 " << packRecursive(n, W, w, v) << endl;
break;
}
default:
{
cout << "输入错误!" << endl;
break;
}
}
cout << "------------------------------------------------" << endl;
delete w;
delete v;
for (int i = 0; i <= n; ++i) {
delete[] T[i];
}
delete[] T;
system("pause");
return 0;
}