0-1背包问题(分支限界法)

分支限界法

是一种求解组合优化问题的数学方法。它利用分支定界技术,在搜索解空间的过程中,根据界值信息剪去一些分支,从而减少搜索空间,提高搜索效率。

在分支限界法中,首先将问题的解空间分解成一个个子问题,然后对每个子问题进行求解。在解的搜索过程中,利用界值信息对当前解空间进行限制,如果当前解空间已经无法得到更优解,就停止搜索该分支。

通过不断地分解原问题,识别出次优解和无效解,分支限界法可以有效地帮助加快组合优化问题的求解过程。它在很多实际问题中得到了广泛应用,例如任务分配、旅行商问题等。

这里是来解决0-1背包问题

0-1背包问题

重要点:

⭐解n元组(解空间):{x1,x2,x3,...,xn}  xi∈{0,1}

⭐约束条件:\sum_{i=1}^{n}wixi<=W

⭐目标函数:max \sum_{i=1}^{n}vixi

⭐限界函数: ub=v+(W-w)×(v_{i+1}/w_{i+1})

图示:

❤算法思路❤:


1. 创建一个结构体Node用来存储每次搜索的状态信息,包括当前背包剩余容量、当前总价值、当前选择的物品、当前选择的物品数量等。
2. 将所有物品按照单位重量的价值进行排序。
3. 创建一个优先队列queue,用来存储每次搜索的状态,按照价值上界进行排序。
4. 初始化一个初始状态node0,背包剩余容量为背包总容量,总价值为0,选择的物品为空,数量为0。
5. 将node0插入优先队列queue中。
6. 循环直到queue为空或者找到最优解为止:
   - 取出队首元素node,并判断node的价值上界是否小于当前最优解,如果是则剪枝。
   - 遍历剩余未选择的物品,对每个物品进行尝试选择或者不选择的操作,计算价值上界和重量是否超过背包容量,然后将生成的新状态插入queue中。
7. 返回找到的最优解。

伪代码:

struct Node {
    int remaining_capacity; // 剩余容量
    int total_value; // 当前总价值
    int items_chosen[]; // 当前选择的物品
    int num_items; // 物品数量
    float upper_bound; // 价值上界
};

int knapsack(vector<int> weights, vector<int> values, int capacity) {
    sort(items.begin(), items.end(), compare); // 按照单位重量的价值进行排序
    priority_queue<Node> q;
    
    Node initial_node = {capacity, 0, {}, 0, calculate_upper_bound(0, capacity, 0, weights, values)};
    q.push(initial_node);

    while (!q.empty()) {
        Node node = q.top();
        q.pop();

        if (node.upper_bound < best_solution) {
            continue; // 剪枝
        }

        for (int i = node.num_items; i < weights.size(); i++) {
            // 选择当前物品
            Node new_node1 = {node.remaining_capacity - weights[i], node.total_value + values[i], node.items_chosen, node.num_items + 1, node.upper_bound};
            new_node1.items_chosen.push_back(i);
            new_node1.upper_bound = calculate_upper_bound(i + 1, new_node1.remaining_capacity, new_node1.total_value, weights, values);
            
            if (new_node1.remaining_capacity >= 0 && new_node1.upper_bound > best_solution) {
                q.push(new_node1);
            }

            // 不选择当前物品
            Node new_node2 = {node.remaining_capacity, node.total_value, node.items_chosen, node.num_items + 1, node.upper_bound};
            new_node2.upper_bound = calculate_upper_bound(i + 1, new_node2.remaining_capacity, new_node2.total_value, weights, values);
            
            if (new_node2.upper_bound > best_solution) {
                q.push(new_node2);
            }
        }
    }

    return best_solution;
}

总结:

0-1背包问题的分支限界法是一种通过搜索状态空间树来解决问题的方法。其优势在于:
1. 可以通过价值上界进行剪枝,减少搜索空间,提高算法效率。
2. 可以找到最优解,保证解的正确性。

然而,分支限界法也存在一些劣势:
1. 时间复杂度较高,对于较大规模的问题可能会耗费较长时间。
2. 需要对问题进行适当的建模,设计合适的价值上界函数。
3. 难以处理连续的状态空间,只适用于离散空间的问题。

总的来说,分支限界法是一种有效的解决0-1背包等组合优化问题的算法,但在实际应用中需要根据具体问题的规模和特点来选择合适的算法。
 

  • 18
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值