Els algorismes greedy (o golafres) són una tècnica de disseny d'algorismes que construeixen una solució pas a pas, escollint en cada pas l'opció que sembla ser la millor en aquell moment. Aquesta tècnica és molt útil per a problemes d'optimització on es busca una solució òptima o gairebé òptima.

Conceptes Clau

  1. Elecció Greedy: En cada pas, es fa una elecció que sembla ser la millor en aquell moment.
  2. Propietat de Subestructura Òptima: Una solució òptima global es pot construir a partir de solucions òptimes locals.
  3. Propietat de Greedy Choice: La millor elecció en cada pas condueix a una solució òptima global.

Exemples d'Algorismes Greedy

  1. Problema del Camí Més Curt (Algorisme de Dijkstra)

L'algorisme de Dijkstra és un exemple clàssic d'algorisme greedy que resol el problema del camí més curt en un graf amb pesos no negatius.

Pseudocodi

function Dijkstra(G, s):
    for each vertex v in G:
        dist[v] := infinity
        prev[v] := undefined
    dist[s] := 0
    Q := set of all nodes in G
    while Q is not empty:
        u := vertex in Q with min dist[u]
        remove u from Q
        for each neighbor v of u:
            alt := dist[u] + length(u, v)
            if alt < dist[v]:
                dist[v] := alt
                prev[v] := u
    return dist[], prev[]

Explicació

  1. Inicialització: Es defineixen les distàncies inicials a tots els nodes com a infinites, excepte el node d'origen s que es defineix com a 0.
  2. Selecció Greedy: Es selecciona el node u amb la menor distància actual.
  3. Actualització: Es revisen tots els veïns del node u i s'actualitzen les distàncies si es troba un camí més curt.

  1. Problema de la Motxilla Fraccionària

En aquest problema, es busca omplir una motxilla amb objectes de diferents pesos i valors per maximitzar el valor total, però es permet fraccionar els objectes.

Pseudocodi

function KnapsackFractional(W, items):
    for each item in items:
        item.value_per_weight := item.value / item.weight
    sort items by value_per_weight in descending order
    total_value := 0
    for each item in items:
        if W == 0:
            return total_value
        if item.weight <= W:
            W := W - item.weight
            total_value := total_value + item.value
        else:
            total_value := total_value + item.value_per_weight * W
            W := 0
    return total_value

Explicació

  1. Inicialització: Es calcula el valor per unitat de pes per a cada objecte.
  2. Ordenació: Es classifiquen els objectes en ordre descendent segons el valor per unitat de pes.
  3. Selecció Greedy: Es seleccionen els objectes en ordre fins que la motxilla està plena o no es poden afegir més objectes.

Exercici Pràctic

Problema: Monedes per Canvi

Donat un conjunt de denominacions de monedes i una quantitat de diners, troba el nombre mínim de monedes necessàries per fer el canvi.

Pseudocodi

function MinCoins(coins, amount):
    sort coins in descending order
    num_coins := 0
    for each coin in coins:
        while amount >= coin:
            amount := amount - coin
            num_coins := num_coins + 1
    if amount > 0:
        return -1  // No es pot fer el canvi exactament
    return num_coins

Explicació

  1. Ordenació: Es classifiquen les monedes en ordre descendent.
  2. Selecció Greedy: Es seleccionen les monedes més grans possibles fins que es completi la quantitat.

Exercici

Implementa l'algorisme en el teu llenguatge de programació preferit i prova'l amb les següents denominacions i quantitats:

  • Denominacions: [1, 5, 10, 25]
  • Quantitat: 63

Solució

def min_coins(coins, amount):
    coins.sort(reverse=True)
    num_coins = 0
    for coin in coins:
        while amount >= coin:
            amount -= coin
            num_coins += 1
    if amount > 0:
        return -1  # No es pot fer el canvi exactament
    return num_coins

# Prova
coins = [1, 5, 10, 25]
amount = 63
print(min_coins(coins, amount))  # Sortida esperada: 6 (2x25, 1x10, 3x1)

Resum

Els algorismes greedy són una tècnica poderosa per resoldre problemes d'optimització, però no sempre garanteixen una solució òptima. És important assegurar-se que el problema té les propietats necessàries perquè un algorisme greedy funcioni correctament. En aquest mòdul, hem vist exemples clàssics com l'algorisme de Dijkstra i el problema de la motxilla fraccionària, així com un exercici pràctic per reforçar els conceptes apresos.

© Copyright 2024. Tots els drets reservats