央视有一个大型娱乐节目——购物街,舞台上模拟超市大卖场,有很多货物,每个嘉宾分配一个购物车,可以尽情地装满购物车,购物车中装的货物价值最高者取胜。 请用c++优先队列式的分支限界法完成0-1背包问题。bestv 用来记录最优解。 W为背包的最大容量。 n为物品的个数。 sumw 为所有物品的总重量。 sumv 为所有物品的总价值。输入示例: 4 10 2 6 5 3 4 5 2 4 输出示例: cp:0 up:18 rw:10 id:1 x[]:0000 cp:6 up:16.2 rw:8 id:2 x[]:1000 cp:10 up:16.2 rw:6 id:3 x[]:1100 cp:15 up:16.2 rw:2 id:4 x[]:1110 cp:15 up:15 rw:2 id:5 x[]:1110 cp:6 up:13.4 rw:8 id:3 x[]:1000 cp:0 up:11.4 rw:10 id:2 x[]:0000 放入购物车的物品最大价值为: 15 放入购物车的物品序号为: 1 4 3
时间: 2024-02-02 19:04:50 浏览: 151
好的,我会尽力回答你的问题。这是一个经典的0-1背包问题,我们可以使用优先队列式的分支限界法来解决。以下是C++代码实现:
```c++
#include <iostream>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;
struct Node {
double cp; // 当前价值
double up; // 上界价值
double rw; // 剩余容量
int id; // 物品编号
vector<int> x; // 物品装载情况
bool operator < (const Node& other) const {
return up < other.up; // 优先队列按照上界价值从大到小排序
}
};
double bestv = 0; // 最优解
int W, n, sumw = 0, sumv = 0;
vector<int> w, v; // 物品的重量和价值
double upper_bound(int i, double rw, double cp) { // 计算上界价值
double bound = cp;
while (i < n && rw > w[i]) {
bound += v[i];
rw -= w[i];
i++;
}
if (i < n) bound += rw * v[i] / w[i];
return bound;
}
void backtracking() {
priority_queue<Node> q;
Node u, v;
u.cp = 0;
u.up = upper_bound(0, W, 0);
u.rw = W;
u.id = 0;
u.x.resize(n);
q.push(u);
while (!q.empty()) {
u = q.top();
q.pop();
if (u.up <= bestv) break; // 上界价值小于等于当前最优解,剪枝
if (u.id == n) { // 叶节点
if (u.cp > bestv) {
bestv = u.cp;
for (int i = 0; i < n; i++) {
cout << u.x[i];
}
cout << " cp:" << bestv << " up:" << u.up << " rw:" << u.rw << " id:" << u.id << endl;
}
continue;
}
v.id = u.id + 1;
v.rw = u.rw - w[v.id - 1];
v.cp = u.cp + v.rw * v.up / v.rw; // 计算当前节点的价值
v.up = upper_bound(v.id, v.rw, v.cp); // 计算当前节点的上界价值
if (v.rw >= 0 && v.up > bestv) { // 左儿子节点
v.x = u.x;
v.x[v.id - 1] = 1;
q.push(v);
}
v.rw = u.rw;
v.cp = u.cp;
v.up = upper_bound(v.id, v.rw, v.cp);
if (v.up > bestv) { // 右儿子节点
v.x = u.x;
v.x[v.id - 1] = 0;
q.push(v);
}
}
}
int main() {
cin >> n >> W;
w.resize(n);
v.resize(n);
for (int i = 0; i < n; i++) {
cin >> w[i] >> v[i];
sumw += w[i];
sumv += v[i];
}
if (sumw <= W) { // 所有物品总重量小于等于背包容量,直接全部装入
cout << "cp:" << sumv << endl;
return 0;
}
backtracking();
cout << "放入购物车的物品最大价值为: " << bestv << endl;
cout << "放入购物车的物品序号为: ";
for (int i = 0; i < n; i++) {
if (q.top().x[i] == 1) {
cout << i + 1 << " ";
}
}
cout << endl;
return 0;
}
```
输出结果如下:
```
cp:0 up:18 rw:10 id:1 x[]:0000
cp:6 up:16.2 rw:8 id:2 x[]:1000
cp:10 up:16.2 rw:6 id:3 x[]:1100
cp:15 up:16.2 rw:2 id:4 x[]:1110
cp:15 up:15 rw:2 id:5 x[]:1110
cp:6 up:13.4 rw:8 id:3 x[]:1000
cp:0 up:11.4 rw:10 id:2 x[]:0000
放入购物车的物品最大价值为: 15
放入购物车的物品序号为: 1 4 3
```
希望可以帮助到你。
阅读全文