如何解决时间 O(NW) 空间 O(W) 中的有界背包问题
我正在尝试在 O(NW) 时间和 O(W) 空间中实现有界背包问题,其中 N 是项目数,W 是容量。
有界背包问题:
有N种物品(物品i的k_i个副本,权重w_i,成本c_i)。使重量小于或等于 W 的物品的总成本最大化。
我的方法:
使用动态规划,创建一个表 DP(行是项目,列是容量,DP[i][j] 是项目 1、2、...、i 的最大成本,总重量不大于 j)。答案将是 DP[N] 的最大值。要完成第 i 行,我们只需要第 i - 1 行的值,因此,我们可以通过仅跟踪两行来计算最后一行。因此,O(W) 空间。
因此,使用队列我们可以一次性计算所有类型为 DP[ i ][start + step * w_i] 的单元格,这意味着我们可以在 O(W) 时间内完成每一行。 (我使用 O(1) 分摊时间最大操作的队列)
这是我的实现:
#include <iostream>
#include <vector>
#include <algorithm>
#include <deque>
class MyQueue {
std::deque<int64_t> Deq_;
std::deque<int64_t> Max_;
public:
void push(int64_t element) {
Deq_.push_back(element);
while (!Max_.empty() and Max_.back() < element) {
Max_.pop_back();
}
Max_.push_back(element);
}
void pop() {
if (Max_.front() == Deq_.front()) {
Max_.pop_front();
}
Deq_.pop_front();
}
int max() {
return Max_.front();
}
};
int main() {
int number_of_items,capacity;
std::cin >> number_of_items >> capacity;
std::vector<int64_t> dp_cur(capacity + 1,0);
std::vector<int64_t> dp_prev(capacity + 1,0);
int64_t weight,cost,num;
for (int item = 0; item < number_of_items; ++item) {
dp_cur.swap(dp_prev);
std::cin >> weight >> cost >> num;
for (int start = 0; start < weight; ++start) {
if (item == 0) {
for (int step = 0; start + step * weight < capacity + 1; ++step) {
if (step == 0) {
dp_cur[start + step * weight] = 0;
} else if (step < num + 1) {
dp_cur[start + step * weight] = dp_cur[start + (step - 1) * weight] + cost;
} else {
dp_cur[start + step * weight] = dp_cur[start + (step - 1) * weight];
}
}
} else {
MyQueue que;
int64_t penalty = cost;
for (int step = 0; start + step * weight < capacity + 1; ++step) {
penalty -= cost;
if (step > 1) {
if (step > num) {
que.pop();
}
dp_cur[start + step * weight] =
std::max(dp_prev[start + step * weight],que.max() - penalty);
} else if (step == 1) {
dp_cur[start + step * weight] =
std::max(dp_prev[start + step * weight],dp_cur[start] + cost);
} else {
dp_cur[start + step * weight] = dp_prev[start + step * weight];
}
que.push(dp_prev[start + step * weight] + penalty);
}
}
}
}
std::cout << *std::max_element(dp_cur.begin(),dp_cur.end());
return 0;
}
输入格式:
第一行包含 N 和 W。接下来的 N 行包含 w_i、c_i、k_i。
问题是我的实现在某些测试中给出了错误的解决方案(我看不到它的内容),而且我的第二个实现(更糟糕的渐近)似乎也有同样的问题。你能告诉我问题可能出在哪里或者我在哪里可以找到测试用例吗?我只找到了 this problem,但我的(改编的)解决方案通过了所有测试。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。