第一题 6-13 子集树问题
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
#include <climits>
using namespace std;
// 节点结构体
struct Node {
int level; // 当前处理到第几个集装箱
int weight; // 当前总重量
int remaining_capacity; // 剩余的载重量
vector<int> selected; // 已选择的集装箱重量
// 构造函数
Node(int lvl, int wgt, int capacity, vector<int> sel) : level(lvl), weight(wgt), remaining_capacity(capacity), selected(sel) {}
};
// 上界函数
int upper_bound(const vector<int>& weights, int level, int current_weight, int remaining_capacity) {
int bound = current_weight;
for (int i = level + 1; i < weights.size(); ++i) {
if (weights[i] <= remaining_capacity) {
remaining_capacity -= weights[i];
bound += weights[i];
} else {
bound += remaining_capacity;
break;
}
}
return bound;
}
// 主函数
pair<int, vector<int>> knapsack(int n, int c, vector<int>& weights) {
sort(weights.begin(), weights.end(), greater<int>()); // 对集装箱按重量降序排序
queue<Node> q;
q.push(Node(-1, 0, c, {})); // 从根节点开始
int max_weight = 0;
vector<int> best_selection;
while (!q.empty()) {
Node u = q.front();
q.pop();
if (u.level == n - 1) continue;
// 左子节点:选择下一个集装箱
int next_weight = u.weight + weights[u.level + 1];
if (next_weight <= c) {
vector<int> next_selected = u.selected;
next_selected.push_back(weights[u.level + 1]);
Node v(u.level + 1, next_weight, u.remaining_capacity - weights[u.level + 1], next_selected);
if (v.weight > max_weight) {
max_weight = v.weight;
best_selection = v.selected;
}
// 计算左子节点的上界
int v_bound = upper_bound(weights, v.level, v.weight, v.remaining_capacity);
if (v_bound > max_weight) {
q.push(v);
}
}
// 右子节点:不选择下一个集装箱
Node v(u.level + 1, u.weight, u.remaining_capacity, u.selected);
// 计算右子节点的上界
int v_bound = upper_bound(weights, v.level, v.weight, v.remaining_capacity);
if (v_bound > max_weight) {
q.push(v);
}
}
return {max_weight, best_selection};
}
int main() {
int n, c;
cin >> n >> c;
vector<int> weights(n);
for (int i = 0; i < n; ++i) {
cin >> weights[i];
}
auto result = knapsack(n, c, weights);
int max_weight = result.first;
vector<int> best_selection = result.second;
cout << max_weight << endl;
return 0;
}
第二题 电路板排列问题
最小长度电路板排列问题(回溯)_最小长度电路板排列问题回溯法-CSDN博客https://blog.csdn.net/Jhno99/article/details/78658324?ops_request_misc=&request_id=&biz_id=102&utm_term=xmu6-11%20%E6%9C%80%E5%B0%8F%E9%95%BF%E5%BA%A6%E7%94%B5%E8%B7%AF%E6%9D%BF%E6%8E%92%E5%88%97%E9%97%AE%E9%A2%98&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-1-78658324.142^v100^pc_search_result_base7&spm=1018.2226.3001.4187