📘 CodingMarble Learn

Tecniche di progettazione degli algoritmi

Per progettare un algoritmo, prima si specifica il problema: i dati in ingresso (input), il risultato atteso (output) e le condizioni. Poi si scrivono passi chiari e finiti, in linguaggio naturale, come elenco, pseudocodice o diagramma di flusso. I problemi grandi si dividono dall'alto verso il basso in parti più piccole (raffinamento per passi) oppure si costruiscono dal basso con piccoli pezzi già collaudati. Tecniche classiche: forza bruta (provare tutto), divide et impera (dividi, risolvi, combina; dimezzare come nella ricerca binaria e nel merge sort), greedy (prendere ogni volta la scelta che sembra migliore; veloce ma non sempre ottimale), programmazione dinamica (risolvere ogni sottoproblema una sola volta e salvarlo in una tabella) e backtracking (provare una scelta e annullarla davanti a un vicolo cieco). Si sceglie la tecnica e le strutture dati (array, pile, alberi binari) controllando correttezza ed efficienza (complessità temporale).

🎬 Storia passo dopo passo

  1. Prima si specifica il problema. Input: 8 numeri. Output: il più grande. Passi: guarda ogni scatola e tieni il più grande trovato finora.
  2. Divide et impera: per trovare un numero da 1 a 16, chiedi del numero a metà e butta via metà. Bastano 4 domande.
  3. Greedy: prendi sempre la moneta più grande che entra. È veloce, ma per 6 con monete 1, 3, 4 dà 3 monete, non le 2 migliori.
  4. Programmazione dinamica: risolvi prima le somme piccole e salva ogni risposta in una tabella. La tabella trova 6 = 3 + 3.
  5. Backtracking: cammina lungo un percorso; davanti a un vicolo cieco torna all'ultima scelta e prova un'altra strada, fino all'uscita.
  6. Tocca a te: scegli una somma e le monete. Prevedi: il greedy dà il minor numero di monete? Confronta con la DP.

Suggerimento: trascina la scena 3D per ruotarla. Usa due dita per zoomare.

🤔 Dubbi comuni, chiariti

Perché scrivere input e output prima di programmare?

Se non sai esattamente che cosa entra e che cosa deve uscire, non puoi controllare se i passi sono giusti.

Come possono bastare 4 domande per 16 numeri?

Ogni risposta butta via metà: 16, 8, 4, 2, 1. Le scatole grigie mostrano la metà eliminata.

Se il greedy può sbagliare, perché usarlo?

È molto veloce e semplice, e per molti problemi (monete normali, attività che finiscono prima) è dimostrato corretto.

In che cosa la DP è diversa dal provare tutto?

Risolve ogni somma piccola una sola volta e la riusa, così la tabella cresce passo dopo passo invece di esplorare ogni combinazione.

Il backtracking ricomincia dall'inizio?

No. Torna indietro solo fino all'ultimo bivio con una strada non ancora provata, poi continua.

Come faccio a sapere se il greedy funziona con le mie monete?

Confrontalo con la DP per molte somme. Prova le monete 1, 7, 10 nel gioco libero.

Specificare un problema: input, output e passi

Prima di scrivere codice, descrivi il problema in modo preciso. Questa è la specifica.

Scrivere i passi

Un algoritmo è un elenco finito di passi chiari che trasforma qualsiasi input valido nell'output giusto. Lo puoi scrivere come:

Provalo a mano su input piccoli, anche quelli difficili (tutti uguali, numeri negativi, un solo numero).

Progettazione top-down e bottom-up

Top-down (raffinamento per passi): parti dall'intero compito, dividilo in pochi passi grandi, poi dividi ancora ogni passo finché ogni parte è facile da programmare. Esempio: "Fare la pagella" → leggere i voti → calcolare le medie → assegnare i giudizi → stampare.

Bottom-up: prima costruisci e collauda piccoli pezzi riutilizzabili (una funzione che trova il massimo, una che ordina), poi li unisci nel programma completo.

I progetti veri usano entrambi: si pianifica top-down, si costruisce e si collauda bottom-up.

Divide et impera e il metodo del dimezzamento

Divide et impera ha tre mosse: dividi il problema in parti più piccole dello stesso tipo, risolvi ogni parte (spesso con la ricorsione), combina le risposte.

Algoritmi greedy

Un algoritmo greedy ("goloso") fa la scelta che sembra migliore adesso e non la cambia mai.

Ma il greedy non è sempre giusto: con monete 1, 3, 4, pagare 6 in modo greedy dà 4 + 1 + 1 (3 monete), mentre 3 + 3 ne usa 2. Per fidarti di un metodo greedy devi dimostrarlo, oppure confrontarlo con un metodo sicuro.

Programmazione dinamica e backtracking

Programmazione dinamica (DP)

Quando gli stessi problemi più piccoli si ripetono, risolvi ciascuno una volta sola e salva la risposta in una tabella. Minimo di monete per la somma a: best[a] = 1 + min(best[a - c]) sulle monete c ≤ a, partendo da best[0] = 0. Per monete 1, 3, 4: best = 0, 1, 2, 1, 1, 2, 2. Riempire la tabella dal piccolo al grande è bottom-up; la ricorsione con una memoria è top-down (memoizzazione). Vedi la lezione separata sulla programmazione dinamica per saperne di più.

Backtracking

Costruisci una soluzione una scelta alla volta. Se una scelta rompe una regola o porta a un vicolo cieco, annullala e prova l'opzione successiva. Si usa per labirinti, Sudoku, il problema delle N regine e per elencare tutti i sottoinsiemi. È una forza bruta attenta: salta interi rami che non possono funzionare.

Forza bruta

Prova ogni risposta possibile. È sempre corretta, ma spesso molto troppo lenta (2ⁿ sottoinsiemi, n! ordinamenti).

Scegliere una tecnica: correttezza, efficienza e strutture dati

TecnicaSi usa quandoEsempioTempo tipico
Forza brutal'input è piccolissimoprovare tutte le password di 3 cifrespesso 2ⁿ o n!
Divide et imperale parti sono indipendentiricerca binaria, merge sortO(log n), O(n log n)
Greedyuna buona scelta locale è dimostrata sicurascelta di attività, restoO(n log n)
Programmazione dinamicai sottoproblemi si ripetonoresto con monete, cammini minimidimensione della tabella
Backtrackingricerca con regolelabirinto, Sudokuesponenziale, ma con potatura

Giustificala

Correttezza: mostra che l'algoritmo si ferma sempre e dà l'output giusto (un invariante di ciclo, una dimostrazione o test sui casi limite). Efficienza: conta i passi al crescere di n (Big O) e confrontali con altri metodi.

Le strutture dati aiutano

Array per le tabelle (DP), pile per il backtracking (ricordano dove tornare), code per la ricerca livello per livello. Un albero binario memorizza i dati in modo che ogni nodo abbia al massimo due figli; in un albero binario di ricerca le chiavi più piccole vanno a sinistra e quelle più grandi a destra, così la ricerca dimezza il lavoro a ogni livello, proprio come la ricerca binaria.

Prova tu: monete e gioco dell'indovino

  1. Gioca con un amico a indovinare un numero da 1 a 100. Chiedi sempre del numero a metà. Riesci a vincere sempre in 7 domande? (2⁷ = 128.)
  2. Con monete 1, 3, 4, scrivi su carta la tabella DP per le somme da 0 a 10. Dove sbaglia il greedy?
  3. Apri l'ultimo passo 3D. Prova monete 1, 7, 10 e somma 14. Il greedy dà 10 + 1 + 1 + 1 + 1; la DP dà 7 + 7.
  4. Scrivi un elenco di passi per "trovare il numero più piccolo di una lista" e provalo su 5, 5, 5 e su un solo numero.

Formule e definizioni chiave

Esempi svolti

1. Scrivi una specifica e un elenco di passi per trovare il più grande di n numeri.

Input: n ≥ 1 numeri. Output: il più grande. Passi: 1. migliore ← primo numero. 2. Per ogni altro numero x: se x > migliore, migliore ← x. 3. Restituisci migliore. Per 4, 9, 2, 7, 12, 5, 10, 3 l'output è 12 dopo 7 confronti.

2. Quante domande servono con il dimezzamento per trovare un numero da 1 a 1000?

Ogni domanda dimezza l'intervallo: 1000 → 500 → 250 → 125 → 63 → 32 → 16 → 8 → 4 → 2 → 1. Sono 10 domande (2¹⁰ = 1024 ≥ 1000).

3. Paga 87 in modo greedy con monete 50, 20, 10, 5, 2, 1.

50 (restano 37), 20 (17), 10 (7), 5 (2), 2 (0): 50 + 20 + 10 + 5 + 2 = 5 monete.

4. Riempi la tabella DP per monete 1, 3, 4 fino alla somma 7.

best[0]=0, [1]=1, [2]=2, [3]=1, [4]=1, [5]=min(best4, best2, best1)+1=2, [6]=min(best5, best3, best2)+1=2, [7]=min(best6, best4, best3)+1=2 (3 + 4).

5. Attività (inizio-fine): A 9-11, B 10-12, C 11-13, D 12-14, E 13-15. Scegli il maggior numero di attività che non si sovrappongono.

Greedy per fine più vicina: A (finisce alle 11), poi C (inizia alle 11, finisce alle 13), poi E (inizia alle 13). 3 attività: A, C, E.

6. Pianifica top-down: un programma che dice a una classe la media dei voti e lo studente migliore.

Livello 1: leggere i dati → calcolare → stampare. Livello 2: leggere nomi e voti in liste; calcolare totale e media; trovare il voto massimo e il suo nome; stampare entrambi. Poi ogni pezzo si programma e si collauda bottom-up.

Errori comuni

Quiz di allenamento

1. La specifica di un problema deve indicare:
2. La ricerca binaria su 16 elementi ordinati richiede al massimo circa:
3. Quale tecnica prende sempre la scelta che sembra migliore adesso?
4. La programmazione dinamica funziona bene quando:
5. In una ricerca in un labirinto, tornare all'ultimo bivio dopo un vicolo cieco è:

Esercizi: rispondi da solo

Scrivi o scegli la risposta, poi premi Controlla. Usa un suggerimento se sei bloccato; la soluzione completa appare dopo la tua risposta.

Domande frequenti

Quali sono le principali tecniche di progettazione degli algoritmi?

Forza bruta, divide et impera, greedy, programmazione dinamica e backtracking, scelte dopo aver specificato input e output.

Qual è la differenza tra greedy e programmazione dinamica?

Il greedy fa una sola scelta che sembra migliore a ogni passo e non torna mai indietro. La DP considera tutte le scelte per i sottoproblemi piccoli e salva le risposte migliori, quindi trova il vero ottimo quando i sottoproblemi si sovrappongono.

Che cosa sono la progettazione top-down e bottom-up?

Top-down divide l'intero compito in passi più piccoli; bottom-up costruisce e collauda prima le piccole parti e poi le unisce. La maggior parte dei programmi usa entrambe.

Dove si studia

PolandSzkoła podstawowa, klasa VIIUnderstanding, analysing and solving problems
PolandSzkoła podstawowa, klasa VIIIUnderstanding, analysing and solving problems
PolandLiceum ogólnokształcące, klasa IUnderstanding, analysing and solving problems
China高三Electives (选修)

Da studiare prima

Da studiare dopo

Lezioni correlate

Tutte le lezioni di Computer Science