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
- Elecció Greedy: En cada pas, es fa una elecció que sembla ser la millor en aquell moment.
- Propietat de Subestructura Òptima: Una solució òptima global es pot construir a partir de solucions òptimes locals.
- Propietat de Greedy Choice: La millor elecció en cada pas condueix a una solució òptima global.
Exemples d'Algorismes Greedy
- 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ó
- 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. - Selecció Greedy: Es selecciona el node
u
amb la menor distància actual. - Actualització: Es revisen tots els veïns del node
u
i s'actualitzen les distàncies si es troba un camí més curt.
- 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ó
- Inicialització: Es calcula el valor per unitat de pes per a cada objecte.
- Ordenació: Es classifiquen els objectes en ordre descendent segons el valor per unitat de pes.
- 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ó
- Ordenació: Es classifiquen les monedes en ordre descendent.
- 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.
Curs d'Anàlisi i Disseny d'Algorismes
Mòdul 1: Introducció als Algorismes
Mòdul 2: Anàlisi d'Algorismes
- Anàlisi de Complexitat Temporal
- Anàlisi de Complexitat Espacial
- Cases de Complexitat: Millor, Pitjor i Promig
Mòdul 3: Estratègies de Disseny d'Algorismes
Mòdul 4: Algorismes Clàssics
- Cerca Binària
- Ordenació per Inserció
- Ordenació per Mescla (Merge Sort)
- Ordenació Ràpida (Quick Sort)
- Algorisme de Dijkstra
- Algorisme de Floyd-Warshall