class Item:
def __init__(self, value, weight):
self.value = value
self.weight = weight
self.ratio = value / weight
def knapsack_branch_and_bound(max_weight, items):
best_value = 0
best_combination = []
items.sort(key=lambda x: x.ratio, reverse=True)
def bound(node, current_weight, current_value):
if current_weight >= max_weight:
return 0
value_bound = current_value
j = node
total_weight = current_weight
while j < len(items) and total_weight + items[j].weight <= max_weight:
total_weight += items[j].weight
value_bound += items[j].value
j += 1
if j < len(items):
value_bound += (max_weight - total_weight) * items[j].ratio
return value_bound
def explore_node(node, current_weight, current_value, current_combination):
nonlocal best_value, best_combination
if node == len(items) or current_weight > max_weight:
return
if current_value > best_value:
best_value = current_value
best_combination = current_combination.copy()
next_node = node + 1
if current_weight + items[node].weight <= max_weight:
current_combination.append(items[node])
explore_node(next_node, current_weight + items[node].weight, current_value + items[node].value, current_combination)
current_combination.pop()
if bound(next_node, current_weight, current_value) > best_value:
explore_node(next_node, current_weight, current_value, current_combination)
explore_node(0, 0, 0, [])
return best_value, best_combination
max_weight = 50
items = [Item(60, 10), Item(100, 20), Item(120, 30)]
knapsack_branch_and_bound(max_weight, items)