没有重复的背包:最大数量的黄金
Knapsack without repitions: Maximum Amount of Gold
来自 Coursera 的算法工具箱课程。
问题介绍
给你一组金条,你的目标是尽可能多地把金条带入
你的包。每个栏只有一个副本,对于每个栏,您可以接受或不接受
(因此你不能拿一小部分酒吧)。
问题描述
任务。给定金条,求一袋容量为 的最大黄金重量。
输入格式。输入的第一行包含背包的容量和金条的数量。下一行包含整数 0,1, 。 . . ,−1 定义金条的重量。
约束。 1 ≤ ≤ 10^4; 1≤≤300; 0 ≤ 0, . . . , −1 ≤ 10^5.
输出格式。输出容量为 .
的背包能装下的最大黄金重量
我在 C++ 中的解决方案:
const int WEIGHT_MAX = 1000 + 1;
const int ITEMS_COUNT_MAX = 300 + 1;
int optimal_weight(int W, const vector<int> &w) {
int weights[ITEMS_COUNT_MAX][WEIGHT_MAX];
const int w_size = w.size();
for (int i = 0; i <= w_size; i++) {
for (int j = 0; j <= W; j++) {
if (i==0 || j==0)
weights[i][j] = 0;
else if (w[i - 1] <= j)
weights[i][j] = std::max(w[i - 1] + weights[i - 1][j - w[i - 1]], weights[i - 1][j]);
else
weights[i][j] = weights[i - 1][j];
}
}
int result = weights[w_size][W];
return result;
}
为输入
10 3
1 4 8
...它产生以下二维矩阵:
0 0 0 0 0 0 0 0 0 0 0
0 1 1 1 1 1 1 1 1 1 1
0 1 1 1 4 5 5 5 5 5 5
0 1 1 1 4 5 5 5 8 9 9
但是 14 年级学生的第 9 次考试没有通过。评分器不提供它使用的输入。
有人可以指出解决方案中可能存在的注意事项吗?
更新[感谢马特解决]:
必须在堆上分配内存,因为本地堆栈大小不足以容纳大小为 10001х301 的数组。实际上,尝试在堆栈上分配时出现分段错误。
int optimal_weight(int W, const vector<int> &w) {
const int w_size = w.size();
int** weights = new int* [w_size + 1];
for (int i = 0; i <= w_size; i++) {
weights[i] = new int[W + 1];
}
for (int i = 0; i <= w_size; i++) {
for (int j = 0; j <= W; j++) {
if (i==0 || j==0) {
weights[i][j] = 0;
}
else if (w[i - 1] <= j)
weights[i][j] = std::max(w[i - 1] + weights[i - 1][j - w[i - 1]], weights[i - 1][j]);
else
weights[i][j] = weights[i - 1][j];
}
}
int result = weights[w_size][W];
for (int i = 0; i < w_size; i++) {
delete[] weights[i];
}
delete[] weights;
return result;
}
计算没有问题,但最大权重为 10000,而您的矩阵最多只能达到 1001,因此您遇到了缓冲区溢出。
一开始就在堆栈上分配矩阵并不好,当你解决这个问题时情况会更糟。
而且你并不真的需要一个二维矩阵来解决这个问题。
尝试维护一个可访问权重的排序列表。从 [0] 开始并为每个项目添加新的可访问权重。
来自 Coursera 的算法工具箱课程。
问题介绍
给你一组金条,你的目标是尽可能多地把金条带入 你的包。每个栏只有一个副本,对于每个栏,您可以接受或不接受 (因此你不能拿一小部分酒吧)。
问题描述
任务。给定金条,求一袋容量为 的最大黄金重量。 输入格式。输入的第一行包含背包的容量和金条的数量。下一行包含整数 0,1, 。 . . ,−1 定义金条的重量。
约束。 1 ≤ ≤ 10^4; 1≤≤300; 0 ≤ 0, . . . , −1 ≤ 10^5.
输出格式。输出容量为 .
的背包能装下的最大黄金重量我在 C++ 中的解决方案:
const int WEIGHT_MAX = 1000 + 1;
const int ITEMS_COUNT_MAX = 300 + 1;
int optimal_weight(int W, const vector<int> &w) {
int weights[ITEMS_COUNT_MAX][WEIGHT_MAX];
const int w_size = w.size();
for (int i = 0; i <= w_size; i++) {
for (int j = 0; j <= W; j++) {
if (i==0 || j==0)
weights[i][j] = 0;
else if (w[i - 1] <= j)
weights[i][j] = std::max(w[i - 1] + weights[i - 1][j - w[i - 1]], weights[i - 1][j]);
else
weights[i][j] = weights[i - 1][j];
}
}
int result = weights[w_size][W];
return result;
}
为输入
10 3
1 4 8
...它产生以下二维矩阵:
0 0 0 0 0 0 0 0 0 0 0
0 1 1 1 1 1 1 1 1 1 1
0 1 1 1 4 5 5 5 5 5 5
0 1 1 1 4 5 5 5 8 9 9
但是 14 年级学生的第 9 次考试没有通过。评分器不提供它使用的输入。
有人可以指出解决方案中可能存在的注意事项吗?
更新[感谢马特解决]: 必须在堆上分配内存,因为本地堆栈大小不足以容纳大小为 10001х301 的数组。实际上,尝试在堆栈上分配时出现分段错误。
int optimal_weight(int W, const vector<int> &w) {
const int w_size = w.size();
int** weights = new int* [w_size + 1];
for (int i = 0; i <= w_size; i++) {
weights[i] = new int[W + 1];
}
for (int i = 0; i <= w_size; i++) {
for (int j = 0; j <= W; j++) {
if (i==0 || j==0) {
weights[i][j] = 0;
}
else if (w[i - 1] <= j)
weights[i][j] = std::max(w[i - 1] + weights[i - 1][j - w[i - 1]], weights[i - 1][j]);
else
weights[i][j] = weights[i - 1][j];
}
}
int result = weights[w_size][W];
for (int i = 0; i < w_size; i++) {
delete[] weights[i];
}
delete[] weights;
return result;
}
计算没有问题,但最大权重为 10000,而您的矩阵最多只能达到 1001,因此您遇到了缓冲区溢出。
一开始就在堆栈上分配矩阵并不好,当你解决这个问题时情况会更糟。
而且你并不真的需要一个二维矩阵来解决这个问题。
尝试维护一个可访问权重的排序列表。从 [0] 开始并为每个项目添加新的可访问权重。