Professional Documents
Culture Documents
Eficincia de Algoritmos
Guloso
verso 1.6
Guloso
Guloso
Em geral:
uma maneira natural e intuitiva de se resolver
problemas
conduz a algoritmos eficientes
nem sempre conduz ao resultado timo. Portanto,
necessrio justificar (provar) a correo
Guloso
Troco Mnimo
Guloso
Problema: Dado o conjunto de moedas M =
{1, 5, 10, 25, 50, 100}, determinar o nmero
mnimo de moedas para dar um troco de
valor N
Exemplo: N = 37 mnimo de 4 moedas
Guloso
Passo 1: Caracterizar a subestrutura tima
do problema
Seja TM(N) o troco mnimo de N.
(Ex: TM(37) = 4 para M = {1, 5, 10, 25, 50, 100})
Assuma N > 0. Suponha que m M pertence a um troco mnimo
T de N. O que dizer de |T - {m}|?
Guloso
Passo 1: Caracterizar a subestrutura tima
do problema
Afirmamos que |T - {m}| = TM(N - m), pois caso contrrio:
Guloso
Passo 2: Definir o valor de uma soluo
tima de cada subproblema recursivamente
Seja m M.
Se soubssemos que m pertence a um troco mnimo de N, ento
TM(N) = 1 + TM(N-m). Mas no sabemos. O que fazer?
Testar todas as possveis escolhas!
Guloso
Passo 2: Definir o valor de uma soluo
tima de cada subproblema recursivamente
Recurso:
TM(N) = 0, se N = 0
TM(N) = min { 1 + TM(N-m) | m M, m N }, se N > 0
Alguma diviso particularmente interessante?
Guloso
Passo 3: Caracterizar a escolha gulosa
Usar a moeda de maior valor! Funciona, pois...
Guloso
Prova de Correo da Escolha Gulosa:
Em um troco mnimo, a quantidade mxima de moedas de cada tipo
a seguinte:
Moeda
10
25
50
100
# Mximo
Guloso e Programao
Dinmica
Prova de Correo da Escolha Gulosa:
Em um troco mnimo, a quantidade mxima de moedas de cada tipo
a seguinte:
Moeda
10
25
50
100
# Mximo
Guloso e Programao
Dinmica
Prova de Correo da Escolha Gulosa:
Em um troco mnimo, a quantidade mxima de moedas de cada tipo
a seguinte:
Moeda
10
25
50
100
# Mximo
Guloso e Programao
Dinmica
Prova de Correo da Escolha Gulosa:
Em um troco mnimo, a quantidade mxima de moedas de cada tipo
a seguinte:
Moeda
10
25
50
100
# Mximo
Guloso e Programao
Dinmica
Prova de Correo da Escolha Gulosa:
Em um troco mnimo, a quantidade mxima de moedas de cada tipo
a seguinte:
Moeda
10
25
50
100
# Mximo
Guloso e Programao
Dinmica
Prova de Correo da Escolha Gulosa:
Em um troco mnimo, a quantidade mxima de moedas de cada tipo
a seguinte:
Moeda
10
25
50
100
# Mximo
Guloso e Programao
Dinmica
Prova de Correo da Escolha Gulosa:
Em um troco mnimo, a quantidade mxima de moedas de cada tipo
a seguinte:
Moeda
10
25
50
100
# Mximo
Guloso
Passo 4: Computar uma soluo tima de
cada subproblema de forma "top-down"
Guloso
funo TrocoMinimo(val Troco: Inteiro): Famlia
var moeda: Inteiro
incio
se Troco = 0 ento
retornar ( )
seno
moeda mx { m M | m Troco }
retornar ({moeda} U TrocoMinimo(Troco - moeda))
fim-se
fim-funo
... // leitura de N
escrever(TrocoMinimo(N))
Guloso
Passo 5: Transformar o algoritmo recursivo
em iterativo
Guloso
funo TrocoMinimo(val Troco: Inteiro): Famlia
var TM: Famlia //uma lista ligada
moeda: Inteiro
incio
TM
enquanto Troco > 0 faa
moeda mx { m M | m Troco}
TM TM U {moeda}
Troco Troco - moeda
fim-para
retornar (TM)
fim-funo
... // leitura de N e M()
escrever (TrocoMinimo(N))
Guloso
funo TrocoMinimo(val Troco: Inteiro): Famlia
var TM: Famlia //uma lista ligada
moeda: Inteiro
incio
TM
enquanto Troco > 0 faa
moeda mx { m M | m Troco}
TM TM U {moeda}
Troco Troco - moeda
Complexidade de Tempo:
fim-para
O(N.|M|)
retornar (TM)
fim-funo
analisando melhor...
O(TM(N).|M|)
... // leitura de N e M()
escrever (TrocoMinimo(N))
Guloso
funo TrocoMinimo(val Troco: Inteiro): Famlia
var TM: Famlia //uma lista ligada
moeda, mm: Inteiro
incio
TM, mm , |M|
enquanto Troco > 0 faa
enquanto Troco < M(mm) faa mm mm - 1 fim-enquanto
moeda M(mm)
TM TM U {moeda}
Troco Troco - moeda
fim-para
retornar (TM)
fim-funo
... // leitura de N e M() - assumir M ordenado
escrever (TrocoMinimo(N))
Guloso
funo TrocoMinimo(val Troco: Inteiro): Famlia
var TM: Famlia //uma lista ligada
moeda, mm: Inteiro
incio
TM, mm , |M|
enquanto Troco > 0 faa
enquanto Troco < M(mm) faa mm mm - 1 fim-enquanto
moeda M(mm)
TM TM U {moeda}
Troco Troco - moeda
Complexidade de Tempo:
fim-para
O(TM(N) + |M|)
retornar (TM)
fim-funo
... // leitura de N e M() - assumir M ordenado
escrever (TrocoMinimo(N))
Guloso
Por outro lado, qualquer algoritmo que resolva o
problema de Troco Mnimo deve escrever o troco
mnimo ao final de sua computao e deve, no pior
caso, ler todo o conjunto de moedas disponvel para dar
troco. Portanto, a complexidade de resoluo de
qualquer algoritmo para este problema (TM(N) +
|M|)
Portanto, o algoritmo anterior timo
Seleo Mxima de
Atividades
Guloso
Exemplo:
s = (1
e = (4
3
5
0
6
5
7
3
8
5
9
6 8 8 2 12)
10 11 12 13 14)
Guloso
Passo 1: Caracterizar a subestrutura tima
do problema
Assuma que o conjunto de atividades esteja ordenado por ordem de trmino, isto ,
i < j => ei ej
Seja Si,j o conjunto de atividades que esto entre Ai e Aj, isto , atividades que
comeam depois de Ai e terminam antes de Aj (permitimos i = 0 e j = N+1, com o
significado de que no h restrio respectivamente esquerda e direita).
Seja S(i, j) o tamanho de uma seleo tima de atividades de Si,j
Seja S uma seleo tima das atividades de Si,j. Suponha que Az S. Sejam A o
subconjunto de S das atividades que antecedem Az e D aquele das atividades que
sucedem Az. O que dizer de A e D?
Guloso
Passo 1: Caracterizar a subestrutura tima
do problema
Afirmamos que |A| = S(i, z) e |D| = S(z, j), pois caso contrrio:
Guloso
Passo 2: Definir o valor de uma soluo
tima de cada subproblema recursivamente
Se soubssemos que Az pertence a uma seleo tima de Si,j
ento saberamos que:
S(i, j) = 1 + S(i, z) + S(z, j)
Mas no sabemos. O que fazer?
Testar todas as possveis escolhas!
Guloso
Passo 2: Definir o valor de uma soluo
tima de cada subproblema recursivamente
Recurso:
S(i, j) = 0, se Si,j =
S(i, j) = mx {1 + S(i, z) + S(z, j) | i z j}, se Si,j
Note que:
(i) Si,j = para j i
(ii) Adicionamos artificialmente as atividades A0 e AN+1 que respectivamente terminam
antes e comeam depois que qualquer outra atividade. Feito isso, a seleo tima do
problema original claramente S(0, N+1)
Guloso
Passo 3: Caracterizar a escolha gulosa
Teorema: Sejam i < j e Az a atividade de Si,j que termina primeiro.
Ento:
(i) Az pertence a uma seleo tima de Si,j
(ii) Si,z =
Prova: (ii) Se Si,z , ento h uma atividade Am entre Ai e Az.
Neste caso, Am tambm uma atividade de Si,j e termina primeiro
que Az, contradizendo a escolha de Az.
Guloso
Passo 3: Caracterizar a escolha gulosa
Prova (continuao): (i) Seja S uma seleo tima de Si,j e seja
Ak a atividade que primeiro termina em S. Se k = z, ento de fato o
item (i) verdadeiro. Suponha portanto que k z.
Se z < k, ento ez ek. Logo, S' = S - Ak U Az uma outra seleo
tima de Si,j, mostrando que (i) verdadeiro.
Se k < z, ento ek ez. Como Ak Si,j, para no contradizer a
escolha de Az, temos que ek = ez. Novamente, S' = S - Ak U Az
uma outra seleo tima de Si,j, mostrando que (i) verdadeiro.
Guloso
Passo 4: Computar uma soluo tima de
cada subproblema de forma "top-down"
Guloso
funo SelecaoMaxima(val i, j, s(), e(): Inteiro): Conjunto
incio
zi+1
enquanto s(z) < e(i) E z < j faa z z + 1 fim-enquanto
se z < j ento
retornar ({Az} U SelecaoMaxima(z, j, s, e))
seno
retornar ()
fim-se
fim-funo
ler (N, s(1..N), e(1..N))
e(0), s(N+1) min {s(i) | 1 i N} - 1, e(N) + 1
escrever (SelecaoMaxima(0, N+1, s, e))
Guloso
Passo 5: Transformar o algoritmo recursivo
em iterativo
Guloso
funo SelecaoMaxima(val i, j, s(), e(): Inteiro): Conjunto
var Selecao: Conjunto // implementao por lista ligada
incio
zi+1
enquanto z < j faa
enquanto s(z) < e(i) E z < j faa z z + 1 fim-enquanto
Selecao Selecao {Az}
iz
zi+1
Complexidade de Tempo:
fim-enquanto
O(N2)
retornar (Selecao)
(anlise pode melhorar!)
fim-funo
ler (N, s(1..N), e(1..N))
e(0), s(N+1) min {s(i) | 1 i N} - 1, e(N) + 1
escrever (SelecaoMaxima(0, N+1, s, e))
Guloso
funo SelecaoMaxima(val i, j, s(), e(): Inteiro): Conjunto
var Selecao: Conjunto // implementao por lista ligada
incio
para z i + 1 at j faa
se e(i) s(z) ento
Selecao Selecao {Az}
iz
fim-se
fim-para
retornar (Selecao)
Complexidade de Tempo:
fim-funo
(N)
ler (N, s(1..N), e(1..N))
e(0), s(N+1) min {s(i) | 1 i N} - 1, e(N) + 1
escrever (SelecaoMaxima(0, N+1, s, e))
Cdigos de Huffman
Guloso
Introduo:
Guloso
Exemplo:
45
13
12
16
Guloso
Considere recodificar representao dos smbolos: usar um
cdigo de tamanho fixo de 3 bits suficiente para o arquivo em
questo ao invs de 8 bits, ou mesmo usar um cdigo de
tamanho varivel!
a
000
001
010
011
100
101
101
100
111
1101
1100
Guloso
Guloso
C(a) = 1
C(b) = 01
C(c) = 101
Guloso
Observe que um cdigo C pode ser
representado por uma rvore
estritamente binria (i.e., uma
rvore na qual cada n tem 0 ou 2
filhos) tal que:
os smbolos so folhas
cada aresta possui rtulo 0 ou 1
C(x) a sequncia de rtulos
no caminho da raiz at a folha x
a
0
d
0
Guloso
Portanto, o problema de
compactao pode ser reduzido
aquele de determinar uma rvore T
estritamente binria com conjunto
de folhas que minimize:
B(T) = { f(a) |C(a)| : a }
a
0
d
0
Guloso
Passo 1: Caracterizar a subestrutura tima
do problema
Suponha que numa soluo T tima x e y so folhas irms. Seja
T' = T - x - y tal que f(z) = f(x) + f(y) e z pai de x e y. Portanto, T' uma
codificao do alfabeto ' = - {x ,y} U {z}
Note que B(T') = a ' (f(a) |C(a)|) = a -{x,y} (f(a) |C(a)|) + f(z) |C(z)| =
= a -{x,y} (f(a) |C(a)|) + f(x)(|C(x)|-1) + f(y)(|C(y)|-1) =
= a (f(a) |C(a)|) - f(x) - f(y) = B(T) - f(x) - f(y)
Portanto, B(T) = B(T') + f(x) + f(y)
O que dizer de T'?
Guloso
Passo 1: Caracterizar a subestrutura tima
do problema
T' tem que ser codificao tima de '. Caso contrrio, seja T'' uma
codificao tima de ':
Se B(T'') > B(T'), isto contradiria o fato de T'' ser uma codificao
tima de '
Se B(T'') < B(T'), ento seja T''' obtida de T'' colocando-se a e b como
filhos de z com as frequencias originais. Ento:
B(T''') = B(T'') + f(x) + f(y) < B(T') + f(x) + f(y) = B(T), contrariando o
fato de T ser uma codificao tima de
Guloso
Passo 2: Definir o valor de uma soluo
tima de cada subproblema recursivamente
Se soubssemos que x e y so irmos numa soluo tima,
saberamos que:
B(T) = B(T') + f(x) + f(y), onde T' a codificao tima de
' = - {x ,y} U {z} tal que z pai de x e y e f(z) = f(x) + f(y)
Guloso
Passo 2: Definir o valor de uma soluo
tima de cada subproblema recursivamente
Recurso:
B(T) = f(a) + f(b), se = {a, b}
B(T) = min{ B(Txy) + f(x) + f(y) | x, y , x y }, se | | > 0,
onde Txy a codificao tima de xy = - {x ,y} U {z} tal que
z pai de x e y e f(z) = f(x) + f(y)
Guloso
Passo 3: Caracterizar a escolha gulosa
Teorema: Sejam x, y , x y os caracteres de menor frequncia. Existe
uma codificao tima T em que x e y so folhas irms de T
Prova: Seja T' uma codificao tima. Assuma que x e y no so folhas irms em T. Sejam a, b
duas folhas irms de mxima profundidade em T'. Assuma sem perda de generalidade que f(x) f(y) e
f(a) f(b). Naturalmente, f(x) f(a) e f(y) f(b). Como a, b tem mxima profundidade, ento |C(x)| |C
(a)| e |C(y)| |C(b)|.
Construa T a partir de T' trocando de posio os pares x, a e y, b. Logo:
B(T') - B(T) = (f(a)-f(x))|C(a)| + (f(b)-f(y))|C(b)| + (f(x)-f(a))|C(x)| + (f(y)-f(b))|C(y)| =
= (f(a)-f(x))(|C(a)|-|C(x)|) + (f(b)-f(y))(|C(b)|-|C(y)|)
Como f(a)-f(x) 0, |C(a)|-|C(x)| 0, f(b)-f(y) 0, |C(b)|-|C(y)| 0, ento:
B(T') - B(T) 0. Logo, B(T') = B(T) implicando que T uma rvore tima onde x e y so folhas irms de
T.
Guloso
Passo 4: Computar uma soluo tima de
cada subproblema de forma "top-down"
Guloso
registro ArvoreHuffman
Esq, Dir: ^ArvoreHuffman, f: Inteiro, a: Caracter
fim-registro
var x: ^ArvoreHuffman, Arvores: Conjunto
ler (N)
para i 1 at N faa
alocar (x)
ler (x^.a, x^.f)
Arvores Arvores U {x}
fim-para
Huffman(Arvores) //a partir das folhas cresce a rvore at a raiz
escrever (Arvores) //Arvores agora conjunto unitrio
Guloso
procedimento Huffman(ref Arvores: Conjunto)
var x, y, z: ^ArvoreHuffman
incio
se |Arvores| > 1 ento
x T' tal que T'^.f = min { T^.f | T Arvores }
Arvores Arvores - {x}
y T' tal que T'^.f = min { T^.f | T Arvores }
Arvores Arvores - {y}
alocar(z)
z^.Esq, z^.Dir, z^.f x, y, x^.f + y^.f
Arvores Arvores U {z}
Huffman(Arvores)
fim-se
fim-procedimento
Guloso
Passo 5: Transformar o algoritmo recursivo
em iterativo
Guloso
procedimento Huffman(ref Arvores: Conjunto)
var x, y, z: ^ArvoreHuffman
incio
enquanto |Arvores| > 1 faa
x T' tal que T'^.f = min { T^.f | T Arvores }
Arvores Arvores - {x}
y T' tal que T'^.f = min { T^.f | T Arvores }
Arvores Arvores - {y}
alocar(z)
z^.Esq, z^.Dir, z^.f x, y, x^.f + y^.f
Arvores Arvores U {z}
fim-enquanto
fim-procedimento
Guloso
procedimento Huffman(ref Arvores: Conjunto)
var x, y, z: ^ArvoreHuffman
incio
enquanto |Arvores| > 1 faa
x T' tal que T'^.f = min { T^.f | T Arvores }
Arvores Arvores - {x}
y T' tal que T'^.f = min { T^.f | T Arvores }
Arvores Arvores - {y}
alocar(z)
z^.Esq, z^.Dir, z^.f x, y, x^.f + y^.f
Arvores Arvores U {z}
Complexidade de Tempo:
fim-enquanto
(N.lgN)
(implementando Conjunto com um Heap:
fim-procedimento
Extrair mnimo: O(lgN)
Inserir elemento: O(lgN))
Guloso
Min-Heap:
Construo de N
elementos: O(N.lgN)
Inicializar um heap vazio
para cada elemento x
Propriedade Min-Heap:
se x pai de y, ento x y
(i.e., x.chave y.chave)
Inserir x: O(lgN)
colocar x como folha mais
10
19
11
11
11
22
35
30
44
Exerccios
Guloso
1.
Dado um conjunto x1 < < xN de pontos da reta real, determine o menor conjunto de
intervalos fechados de tamanho unitrio que contenham todos os pontos. Ex.: para os
pontos 1, 2.2, 3.1, 4.3, 5.3 o conjunto de intervalos { [1;2], [2;3], [3;4], [4;5], [5;6] } contm
todos os pontos, mas no o menor conjunto que consegue fazer isto pela existncia de {
[1;2], [2.1;3.1], [4.3;5.3] }.
b.
Guloso
1.
(continuao)
c.
Dado um conjunto de atividades A = {A1, ..., AN}, Ai com horrios de incio si e de fim ei,
determinar a cardinalidade do menor subconjunto S A tal que se p um instante dentro
do horrio de alguma atividade de A, ento p um instante dentro do horrio de alguma
atividade de S.