Branch and Bound

Definição

Branch and Bound é uma técnica de busca usada para resolver problemas de otimização combinatória, onde o objetivo é encontrar a melhor solução possível (não apenas uma solução válida). Ao contrário do backtracking, que visa encontrar qualquer solução válida, o Branch and Bound busca sempre a melhor — e evita caminhos improdutivos com base em limites.

Ela combina:

  • Branching: divisão do problema em subproblemas menores (como no backtracking);
  • Bounding: cálculo de limites (bounds) para evitar explorar caminhos que não podem levar à solução ótima.

Se um ramo não puder melhorar a melhor solução já encontrada, ele é descartado — isso reduz drasticamente o espaço de busca.

Por que usar

  • Ideal para problemas em que todas as combinações possíveis são muito numerosas (exponenciais);
  • Mais eficiente que backtracking puro em problemas de otimização;
  • Garante a melhor solução, sem precisar testar todas as possibilidades.

Exemplos clássicos

  • Problema do Caixeiro Viajante (TSP);
  • Mochila Inteira (0/1);
  • Alocação de tarefas com custo mínimo;
  • Programação inteira.

Complexidade

  • Pode chegar a tempo exponencial, mas melhora muito com bons limites (bounds);
  • Depende de estratégias de poda e heurísticas para eficiência.

Exemplo prático (Python) — Mochila 0/1 com poda

Este código resolve o problema da mochila 0/1, buscando o maior valor possível de itens que caibam na mochila. Usa a técnica de Branch and Bound para evitar caminhos que não podem levar à melhor solução.

# Classe que representa um item com valor e peso
class Item:
    def __init__(self, valor, peso):
        self.valor = valor
        self.peso = peso
        self.densidade = valor / peso

# Resolve o problema da mochila 0/1 com Branch and Bound
def mochila_branch_and_bound(capacidade, itens):
    itens.sort(key=lambda x: x.densidade, reverse=True)
    melhor_valor = 0

    # Função recursiva que explora as decisões
    def explorar(indice, valor_atual, peso_atual):
        nonlocal melhor_valor

        if peso_atual > capacidade:
            return  # Excede a capacidade, descarta

        if valor_atual > melhor_valor:
            melhor_valor = valor_atual

        if indice >= len(itens):
            return  # Todos os itens foram considerados

        # Cálculo do limite otimista (bound)
        restante = capacidade - peso_atual
        estimativa = valor_atual
        i = indice
        while i < len(itens) and restante > 0:
            if itens[i].peso <= restante:
                estimativa += itens[i].valor
                restante -= itens[i].peso
            else:
                estimativa += itens[i].densidade * restante
                break
            i += 1

        if estimativa < melhor_valor:
            return  # Poda: não vale a pena continuar

        # Explora com e sem incluir o item atual
        explorar(indice + 1, valor_atual + itens[indice].valor, peso_atual + itens[indice].peso)
        explorar(indice + 1, valor_atual, peso_atual)

    explorar(0, 0, 0)
    return melhor_valor

# Exemplo
itens = [
    Item(valor=60, peso=10),
    Item(valor=100, peso=20),
    Item(valor=120, peso=30)
]

capacidade = 50
resultado = mochila_branch_and_bound(capacidade, itens)
print("Melhor valor possível:", resultado)  # Saída esperada: 220

Saída

Melhor valor possível: 220

Relacionados

Política de Privacidade

Copyright © www.programicio.com Todos os direitos reservados

É proibida a reprodução do conteúdo desta página sem autorização prévia do autor.

Contato: programicio@gmail.com