algorithm exp7

第一题  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博客icon-default.png?t=N7T8https://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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值