Algoritmi e Strutture Dati - II modulo Soluzioni degli esercizi Francesco Pasquale 6 maggio 2015 Esercizio 1. Su una strada rettilinea ci sono n case nelle posizioni 0 c 1 < c 2 < < c n. Bisogna installare dei ripetitori di segnale lungo la strada in modo da garantire che tutte le case siano coperte dal segnale. Ogni ripetitore ha un range d > 0, quindi una casa è coperta dal segnale se ha un ripetitore a distanza minore o uguale a d. Descrivere un algoritmo che prenda in input le posizioni delle case e il range dei ripetitori e restituisca in output le posizioni dove installare i ripetitori in modo che tutte le case siano coperte dal segnale e il numero di ripetitori installati sia il piú piccolo possibile. Dimostrare la correttezza dell algoritmo. Soluzione. L input del problema è dato dalla posizione delle case e dal range dei ripetitori. Una soluzione ammissibile è un insieme di ripetitori, che possiamo indicare con dei numeri r 1,..., r m dove r i rappresenta la posizione del ripetitore i-esimo, tale che ogni casa c sia a distanza minore o uguale a d da almeno un ripetitore. L obiettivo è minimizzare il numero di ripetitori. Possiamo quindi formalizzare il problema in questo modo: input: C = {c 1,..., c n } N con 0 c 1 < c 2 < < c s ; d N sol: S = {r 1,..., r m } N tale che per ogni c C esiste r S con c r d goal: min S Idea: Le case sono ordinate in senso crescente c 1 < < c n. Se devo coprire la prima casa c 1 dovrò posizionare almeno un ripetitore nell intervallo [c 1 d, c 1 +d]. In che punto dell intervallo mi conviene posizionarlo? Una scelta naturale sembra quella di posizionarlo nel punto più lontano possibile verso destra, ossia nel punto c 1 +d, in modo da coprire certamente c 1 e magari anche qualcuna delle case che vengono dopo. Un semplice algoritmo greedy allora è il seguente: - Se c è la posizione della prima casa non ancora coperta, metti un ripetitore r nel punto c + d - Elimina tutte le case coperte da r - Ripeti finchè ci sono case non ancora coperte In pseudocodice: Algorithm 1 Ripetitori input: Le posizioni delle case C = {c 1,..., c n } con 0 c 1 c n ; Il range dei ripetitori d > 0 output: Le posizioni dei ripetitori S = {r 1,..., r k }. S = while C do c = min C r = c + d S = S {r} C = C \ {x C : x r d } return S
L algoritmo trova chiaramente una soluzione ammissibile, perché una casa in posizione c viene tolta dall insieme C solo dopo che è stato inserito in S un ripetitore in posizione r tale che c r d. Quindi quando l algoritmo termina, in al più n iterazioni del ciclo while, tutte le case hanno un ripetitore a distanza minore o uguale a d. Ora dimostriamo che l algoritmo trova effettivamente una soluzione ottima. Per farlo useremo la tecnica greedy stays ahead. In particolare, se S A = {r 1,..., r k } è la soluzione fornita dal nostro algoritmo e S = {r 1,..., r m} è una soluzione ottima ordinata in senso crescente, faremo prima vedere che deve essere r i r i per ogni i. Da questo poi sarà facile vedere che S A è effettivamente una soluzione ottima. Lemma 1.1. Sia S A = {r 1,..., r k } la soluzione fornita dal nostro algoritmo e sia S = {r1,..., r m} una soluzione ottima con r1 < < r m. Allora per ogni i = 1,..., m si ha che ri r i. Proof. Lo dimostriamo per induzione su i: Base (Verifichiamo che r1 r 1): Siccome S deve essere una soluzione ammissibile, ci deve essere un r S che copre la casa c 1, ossia r [c 1 d, c 1 + d]. In particolare deve essere r c 1 + d, ma c 1 + d = r 1 è proprio la posizione del primo ripetitore posizionato dal nostro algoritmo, e siccome r1 è il piú piccolo in S deve essere r1 r r 1. Passo induttivo (Supponiamo che ri r i e dimostriamo che ri+1 r i+1): Consideriamo la (i+1)-esima iterazione del ciclo while del nostro algoritmo. Se l algoritmo ha inserito il ripetitore in posizione r i+1 vuol dire che dopo l iterazione i-esima c era ancora una casa non coperta da nessuno dei ripetitori r 1,..., r i, quindi la sua posizione deve essere c > r i + d, e per l ipotesi induttiva ri r i si ha anche c > ri + d. La casa in posizione c quindi non è coperta dal ripetitore ri della soluzione ottima. Siccome S è una soluzione ammissibile, il ripetitore ri+1 deve coprire la casa c, quindi deve stare nell intervallo [c d, c + d]. In particolare ri+1 c + d e siccome il nostro algoritmo posiziona l (i + 1)-esimo ripetitore in r i+1 = c + d abbiamo che ri+1 r i+1. Theorem 1.2. La soluzione fornita dal nostro algoritmo è ottima. Proof. Sia S A = {r 1,..., r k } la soluzione fornita dal nostro algoritmo e sia S = {r 1,..., r m} una soluzione ottima con r 1 < < r m. Siccome S è ottima, S A deve contenere almeno tanti elementi quanti ne contiene S, ossia k = S A S = m. Ora dimostriamo che in realtà vale l uguaglianza k = S A = S = m. Osserviamo che non ci può essere nessuna casa in posizione c > r m + d, altrimenti quella casa non sarebbe coperta da nessuno dei ripetitori in S. L ultima casa quindi deve essere in posizione c n r m + d. Per il Lemma 1.1, il ripetitore posizionato all m-esima iterazione del ciclo while del nostro algoritmo si trova in posizione r m r m c n d. Quindi dopo al più m iterazioni del ciclo while tutte le case sono coperte e il nostro algoritmo termina. Esercizio 2 (Gara di Triathlon). State organizzando una gara di Triathlon in cui i partecipanti devono completare 20 vasche in piscina, poi percorrere 10 km in bicicletta, infine correre per 3 km. Per evitare confusione in piscina, questa può essere usata da un solo partecipante per volta. Quindi all inizio della gara fate entrare in piscina il primo partecipante, nel momento in 2
cui il primo completa le 20 vasche e inizia il tratto in bicicletta fate entrare in piscina il secondo partecipante e così via. Per ogni partecipante i avete una stima sui tempi p i, b i, c i che impiega rispettivamente in piscina, in bicicletta e di corsa. La gara termina quando tutti i partecipanti hanno completato tutte e tre le specialità. In che ordine fate entrare in piscina i partecipanti per minimizzare la durata della gara? Perché? Soluzione. Indichiamo con n il numero degli atleti e indichiamo con σ S n l ordine con cui li facciamo entrare in piscina, ossia σ(1) indica l atleta che parte per primo, σ(2) quello che parte per secondo, σ(n) quello che parte per ultimo. Se assumiamo che la gara parte all istante 0, allora l atleta che parte per primo dovrebbe arrivare al traguardo all istante p σ(1) + b σ(1) + c σ(1) ; quello che parte per secondo entra in piscina appena il primo esce dalla piscina, quindi dovrebbe arrivare al traguardo all istante p σ(1) + p σ(2) + b σ(2) + c σ(2). In generale quindi, se indichiamo con l σ (j) il tempo atteso in cui l atleta che parte j-esimo arriva al traguardo, abbiamo che l σ (j) = j p σ(k) + b σ(j) + c σ(j) La durata della gara pertato è L σ = max{l σ (j) : j = 1,..., n}. In che modo scegliamo σ per minimuzzare L σ? Idea: Osserviamo che siccome tutti gli atleti devono passare in piscina uno per volta, la gara deve per forza avere un tempo superiore a n i=1 p i. Per comodità chiamiamo P questa quantità P = n i=1 p i. Se per esempio osserviamo l arrivo degli ultimi due atleti, abbiamo che l atleta σ(n), che parte per ultimo, dovrebbe arrivare al traguardo al tempo P +b σ(n) +c σ(n) ; l atleta σ(n 1), che parte per penultimo, dovrebbe arrivare al traguardo al tempo (P p σ(n) )+b σ(n 1) +c σ(n 1). Per minimizzare la durata della gara allora sembra ragionevole mandare i partecipanti che sono più veloci a terra (b i + c i ) per ultimi. Proviamo quindi a usare questa strategia: Ordiniamo i partecipanti per b i + c i decrescente. Per comodità, per ogni atleta i chiamiamo t i il suo tempo a terra, ossia t i = b i + c i. Il nostro ordinamento allora soddisfa t σ(1) t σ(2) t σ(n) (1) Osserviamo che potrebbe esserci più di un ordinamento che soddisfa la condizione (1), perché non stiamo specificando come ci comportiamo se abbiamo due atleti i e h che hanno lo stesso tempo a terra t i = t h. Se tutti i t i sono distinti, allora c è un unico ordinamento σ che soddisfa la (1) e possiamo passare direttamente al Teorema 2.2. Altrimenti, non è difficile convincersi che tutti gli ordinamenti che soddisfano la (1) devono avere la stessa durata; lo dimostriamo formalmente nel prossimo lemma. Lemma 2.1. Tutti gli ordinamenti che soddisfano la (1) hanno la stessa durata. Proof. Due ordinamenti σ e µ che soddisfano la (1) possono differire solo per l ordine dei partecipanti con lo stesso tempo a terra, ossia deve essere t σ(i) = t µ(i) per ogni i. Infatti, se per assurdo così non fosse, prendiamo il più piccolo i per cui t σ(i) t µ(i) e supponiamo senza perdita di generalità che t σ(i) > t µ(i), allora dovrebbe esistere un k > i tale che t µ(k) = t σ(i) > t µ(i), ma questo contraddirrebbe l ipotesi che µ soddisfa la (1). 3
Per quanto riguarda i tempi di arrivo dei singoli atleti nei due ordinamenti ( j ) ( j ) l σ (j) = p σ(k) + t σ(k) e l µ (j) = p µ(k) + t µ(k) (2) in generale non è vero che queste due quantità coincidono per ogni j, ma certamente coincidono se j è l ultimo indice fra quelli che hanno uno stesso tempo a terra. Infatti, se j < n è un indice tale che t σ(j) > t σ(j+1) allora entrambe le somme in (2) sono estese a tutti e soli gli atleti che hanno un tempo a terra minore o uguale a t σ(j), quindi coincidono. Più formalmente, se indichiamo con S l insieme S = {n} {j = 1,..., n 1 : t σ(j) > t σ(j+1) } = {n} {j = 1,..., n 1 : t µ(j) > t µ(j+1) } allora l σ (j) = l µ (j) per ogni j S. Infine osserviamo che se j / S, allora l atleta che parte j-esimo non può arrivare per ultimo né in σ né in µ. Infatti, se j / S allora t σ(j+1) = t σ(j) e t µ(j+1) = t µ(j), quindi in entrambi gli ordinamenti l istante di arrivo dell atleta che parte (j + 1)-esimo è maggiore di quello che parte j-esimo l σ (j + 1) = l σ (j) + p σ (j + 1) > l σ (j) l µ (j + 1) = l µ (j) + p µ (j + 1) > l µ (j) Quindi in entrambi gli ordinamenti un atleta che arriva per ultimo deve essere il j-esimo, per qualche indice j S, ma siccome per tutti i j S si ha l σ (j) = l µ (j) la durata della gara deve essere la stessa in entrambi gli ordinamenti. A questo punto siamo pronti per dimostrare che un ordinamento che soddisfa la (1) minimizza la durata della gara. Theorem 2.2. Sia σ A un ordinamento che soddisfa la (1), allora σ A è ottimo. Proof. Sia σ un ordinamento ottimo. Se σ soddisfa la (1), allora per il Lemma 2.1 il nostro ordinamento σ A ha la stessa durata di σ, quindi σ A è ottimo. Se invece σ non soddisfa la (1) allora deve esistere un j {1,..., n 1} tale che il tempo a terra di σ (j) è più piccolo del tempo a terra di σ (j + 1), t σ (j) < t σ (j+1) (3) Siccome l atleta σ (j) ha un tempo a terra più piccolo di quello di σ (j +1) e parte anche prima deve chiaramente arrivare al traguardo prima di σ (j + 1). Scriviamo esplicitamente il tempo di arrivo dell atleta σ (j + 1), ché ci servirà più avanti l σ (j + 1) = P j 1 + p σ (j) + p σ (j+1) + t σ (j+1) (4) Dove per comodità abbiamo chiamato P j 1 = j 1 p σ(k) il tempo che impiegano in piscina i primi j 1 atleti. Ora proviamo a scambiare l ordine degli atleti σ (j) e σ (j + 1), ossia consideriamo una nuova soluzione µ tale che µ(j) = σ (j + 1) µ(j + 1) = σ (j) µ(k) = σ (k) per ogni k j, j + 1 4
Osserviamo che i tempi di arrivo di tutti gli atleti che partono prima di µ(j) non cambiano, e siccome p σ (j) + p σ (j+1) = p µ(j) + p µ(j+1) anche tutti i tempi di arrivo degli atleti che partono dopo µ(j + 1) sono gli stessi che nell ordinamento σ, ossia l µ (k) = l σ (k) per ogni k j, j + 1 L atleta µ(j) = σ (j + 1) parte prima nell ordinamento µ che nell ordinamento σ, quindi il suo tempo di arrivo nell ordinamento µ è senz altro più piccolo del suo tempo di arrivo nell ordinamento σ : l µ (j) l σ (j + 1). Per quanto riguarda l atleta µ(j + 1) = σ (j) abbiamo che l µ (j + 1) = P j 1 + p µ(j) + p µ(j+1) + t µ(j+1) (5) = P j 1 + p σ (j+1) + p σ (j) + t σ (j) Confrontando la (5) con la (4) e tenendo conto della (3) abbiamo quindi che l µ (j+1) < l σ (j+1). Complessivamente quindi abbiamo dimostrato che l µ (k) l σ (k) per ogni k = 1,..., n. Ma allora la durata della gara con l ordinamento µ è L µ = max{l µ (k) : k = 1,..., n} max{l σ (k) : k = 1,..., n} = L σ Quindi anche µ è una soluzione ottima! Se µ soddisfa la (1) allora per il Lemma 2.1 anche la nostra soluzione σ A è ottima. Altrimenti possiamo ripetere l operazione con cui siamo passati da σ a µ per ottenere una nuova soluzione µ 2 che sarà ancora ottima, e così via finché non arriviamo a una soluzione ordinata 1 come la nostra σ A. 1 L operazione con cui siamo passati da σ a µ non è nient altro che uno step dell algoritmo Bubblesort 5