Você está na página 1de 5

ANÁLISE DE ALGORITMOS

Bacharelado em Ciência da Computação

Lista de Exercícios de revisão (Unidade 2)


Análise de Algoritmos
Prof. Dr. Gabriel Gadelha

1. Por que backtracking favorece frequentemente melhor eficiência que uma busca exaustiva?
Explique.
Uma das principais vantagens do backtracking é que ele é capaz de evitar a busca exaustiva em
todas as soluções possíveis podando aquelas que não atendem às restrições que devem ser
satisfeitas na solução final e, portanto, não são viáveis, reduzindo assim o espaço de busca.

2. Para encontrar todas as possíveis decodificações da mensagem 10010110101011010, codificada


a partir do esquema a = 10, b = 100, c = 10101, d = 10110, podemos usar um método simples que
inicia à esquerda e tenta decodificar (de todas as formas possíveis) caracter a caracter. Ganha-se
eficiência aplicando uma das técnicas estudadas ao problema. Sendo assim, qual técnica de projeto
de algoritmos deve ser aplicada? Explique como proceder para obter 1 (uma) decodificação válida
da mensagem aplicando uma ou mais restrições, favorecendo assim, a eficiência. Você pode exibir a
árvore de busca para esquematizar sua proposta de solução.
Para resolver o problema de encontrar todas as possíveis decodificações da mensagem codificada,
podemos aplicar a técnica de backtracking para reduzir a busca exaustiva de todas as possibilidades.
O procedimento para obter uma decodificação válida seria:
1. Comece com uma string vazia como a decodificação parcial.
2. Analise o próximo caractere da mensagem codificada e tente todas as possibilidades de
decodificação para esse caractere, verificando se é uma das codificações válidas (a, b, c ou d).
3. Se uma decodificação válida for encontrada, adicione o caractere correspondente à
decodificação parcial e avance para o próximo caractere da mensagem codificada.
4. Se nenhuma decodificação válida for encontrada, volte um caractere na decodificação parcial
e tente outra possibilidade para esse caractere. Repita até que uma decodificação válida seja
encontrada ou todas as possibilidades tenham sido testadas.
5. Quando toda a mensagem codificada tiver sido decodificada, a decodificação parcial será
uma das decodificações válidas.
Para aumentar a eficiência do algoritmo de backtracking, podemos adicionar restrições, por exemplo:
 Se a mensagem codificada começar com um caractere inválido (não corresponde a nenhuma
codificação válida), sabemos que a decodificação parcial atual é inválida e podemos encerrar
a busca para essa ramificação.
 Se a decodificação parcial atual já tem um comprimento maior do que a mensagem
codificada, sabemos que essa decodificação é inválida e podemos encerrar a busca para essa
ramificação.

1
ANÁLISE DE ALGORITMOS
Bacharelado em Ciência da Computação

Para exibir a árvore de busca para esquematizar a solução proposta,


podemos usar um diagrama de árvore, onde cada nó representa uma
decodificação parcial e cada ramificação representa uma escolha de
decodificação para o próximo caractere da mensagem codificada. Cada nó
pode ser rotulado com o caractere correspondente a essa decodificação
parcial e cada ramificação pode ser rotulada com a codificação usada para
essa escolha.
Segue ao lado um exemplo de diagrama de árvore para a mensagem
codificada “10010110101011010”:
3. Existe um algoritmo simples para multiplicar matrizes quadradas de tamanho n (número de
linhas e colunas) cuja complexidade é O(n 3) multiplicações. Todavia, determinado cientista propôs
um algoritmo mais eficiente: subdividir as matrizes num produto A x B = C em quatro submatrizes
com a metade do tamanho (e portanto, um quarto de elementos):

Com essa subdivisão, o produto A x B obtém-se pelas equações:

e precisa-se de oito multiplicações de matrizes de tamanho n/2 ao invés de uma multiplicação de


matrizes de tamanho n. A recorrência correspondente, considerando somente multiplicações é:

cuja complexidade é O(n3), que demonstra que essa abordagem não é melhor que o algoritmo
simples (citado no início da questão). Sendo assim, o cientista inventou as seguintes equações:

(cuja verificação é simples). Essas equações contêm somente sete multiplicações de tamanho n/2,
que leva à recorrência:

2
ANÁLISE DE ALGORITMOS
Bacharelado em Ciência da Computação

para o número de multiplicações, cuja complexidade é O(nlg7) = O(n2,81).


Com base no exposto, pode-se considerar que o algoritmo proposto pelo cientista qual das técnicas
de projeto de algoritmos estudadas em sala? Justifique.
Divisão e conquista, pois o cientista iniciou sua proposta de resolução subdividindo seu problema em
problemas menores, em seguida resolveu os problemas menores e, por fim, compôs a solução para
o problema original a partir da resolução dos problemas menores.
4. Por que a recursividade funciona tão bem em divisão-e-conquista, porém não é aplicada em
programação dinâmica? Dica: pense sobre a árvore de recursão gerada para ambas as técnicas!
A recursividade funciona bem em divisão-e-conquista porque essa técnica divide o problema em
subproblemas menores e independentes que podem ser resolvidos recursivamente. Cada
subproblema é resolvido em uma etapa da recursão e seus resultados são combinados para formar a
solução do problema original.
Por outro lado, a programação dinâmica não é geralmente aplicada com recursão direta porque essa
técnica é baseada em memoização1, que armazena os resultados dos subproblemas resolvidos para
evitar recalculá-los.
A programação dinâmica usa uma abordagem bottom-up para resolver os subproblemas em ordem
crescente de complexidade, armazenando os resultados em uma tabela. Isso permite que os
resultados dos subproblemas menores sejam usados para resolver subproblemas maiores, evitando
a repetição desnecessária de cálculos.
5. Suponham que o algoritmo A opera sobre uma árvore binária, sem modificá-la, como segue: A
processa o nodo-raiz da árvore em tempo O(1) e, então, recursivamente chama A para as
subárvores esquerda e direita. Pode-se afirmar que A pode ser substancialmente mais eficiente
usando programação dinâmica? Justifique.
Não, a programação dinâmica não pode ser aplicada para tornar o algoritmo A mais eficiente. A
programação dinâmica é uma técnica de otimização que se aplica a problemas que possuem
subestrutura ótima, ou seja, onde as soluções ótimas dos subproblemas são usadas para construir a
solução ótima do problema original.
No caso do algoritmo A, ele apenas percorre a árvore binária sem modificar seus nodos, e não
envolve a otimização de nenhum problema que possua subestrutura ótima. Portanto, a aplicação de
programação dinâmica não traria nenhum benefício para o algoritmo A, que já possui uma eficiência
assintótica de O(n) (onde n é o número de nodos da árvore), que é a melhor que se pode esperar
para uma operação que percorre todos os nodos de uma árvore.
Assim, não é possível aplicar programação dinâmica para tornar o algoritmo A mais eficiente. A
eficiência do algoritmo A depende principalmente da estrutura da árvore binária e da distribuição
dos nodos, e não de uma técnica específica de programação.
6. Suponha uma série de eventos, por exemplo, as transações feitas na bolsa de valores, na forma
compra Dell, vende HP, compra Google, … Uma certa ação pode acontecer mais de uma vez nessa
sequência. Dada uma outra sequência, decida o mais rápido possível, se ela é uma subsequência da
primeira. O seguinte algoritmo é eficiente para as sequências de tamanho m e n.
Algoritmo Subsequência

Entrada: Sequência S' = s'1...s'm e S = s1...sn

1
O termo "memoization" ou "memoisation" foi inventado por Donald Michie em 1968 e é derivado da palavra latina
"memorandum" ("a ser lembrado"), geralmente truncado como "memo" na língua inglesa, e assim carrega o significado
de "Transformando os resultados de uma função em algo a ser lembrado".
3
ANÁLISE DE ALGORITMOS
Bacharelado em Ciência da Computação

Saída: verdadeiro, se S' ⊆ S //S' é uma subsequência de S


se m > n então
retorne falso
i ← 1
para j ← 1, ..., n faça se s'i = sj então
i ← i + 1
se i>m então retorne verdadeiro
retorne falso

A complexidade do algoritmo é O(n). Sendo assim, é correto afirmar que o algoritmo se baseia em
programação dinâmica? Justifique.
Não, pois se trata do método guloso. Não há, sequer o uso de uma estrutura de dados adicional que
justifique qualquer ideia semelhança com a programação dinâmica.
7. Expliquem a principal diferença entre um algoritmo baseado em PD e um algoritmo guloso para
solucionar um problema.
A principal diferença entre um algoritmo baseado em programação dinâmica e um algoritmo guloso
é a estratégia utilizada para tomar decisões em cada etapa da resolução do problema.
Em resumo, o primeiro faz escolhas locais ótimas a cada etapa, sem levar em conta as implicações
futuras, enquanto o segundo considera todas as escolhas possíveis e determina a escolha ótima
através da comparação de todos os subproblemas possíveis. Como resultado, a programação
dinâmica é geralmente mais precisa e confiável, mas pode ser mais lenta do que um algoritmo
guloso em certas situações.
8. Considere a seguinte fórmula booleana.
(x𝗏y𝗏z)(x𝗏 ¬y)(y𝗏 ¬z)(z𝗏 ¬x)( ¬x𝗏 ¬y𝗏 ¬z)
Qual técnica de projeto de algoritmo pode ser utilizada para resolver o problema da
satisfatibilidade (SAT) dessa fórmula?
Resolva o problema utilizando a técnica proposta e apresente o passo-a-passo.
A técnica de Backtracking pode ser utilizada para resolver o problema da satisfatibilidade (SAT) dessa
fórmula.
Vamos resolver o problema passo a passo:
1. Criar uma lista com as variáveis da fórmula: x, y e z.
2. Atribuir um valor verdadeiro ou falso para a primeira variável, no caso x. Podemos escolher x
= True ou x = False.
3. Avaliar as cláusulas da fórmula que contêm a variável x escolhida no passo 2. Se todas as
cláusulas forem satisfeitas, passamos para a próxima variável da lista (y). Caso contrário,
voltamos para o passo anterior e escolhemos o valor oposto para a variável x.
4. Repetir os passos 2 e 3 para as variáveis y e z, respectivamente.
5. Se chegarmos ao final da lista de variáveis e todas as cláusulas da fórmula forem satisfeitas,
encontramos uma atribuição de valores para as variáveis que satisfaz a fórmula. Caso
contrário, não há solução.
Vamos aplicar essa técnica para a fórmula dada:
1. Lista de variáveis: x, y e z.
2. Escolhemos x = True.
3. Avaliamos as cláusulas que contêm x:

4
ANÁLISE DE ALGORITMOS
Bacharelado em Ciência da Computação

 (x𝗏y𝗏z) é satisfeita para qualquer valor de y e z.


 (x𝗏¬y) é satisfeita para y = False.
 (z𝗏¬x) é satisfeita para z = True.
 Como a cláusula (y𝗏¬z) não é satisfeita para nenhum valor de y e z que respeite as
cláusulas anteriores, voltamos para o passo 2 e escolhemos x = False.
4. Escolhemos y = True.
5. Avaliamos as cláusulas que contêm x e y:
 (x𝗏y𝗏z) é satisfeita para qualquer valor de x, y e z.
 (y𝗏¬z) é satisfeita para z = False.
 (¬x𝗏¬y𝗏¬z) é satisfeita para x = False e z = False.
6. Escolhemos z = True.
7. Avaliamos as cláusulas que contêm x, y e z:
 Todas as cláusulas são satisfeitas.

8. Portanto, encontramos uma atribuição de valores para as variáveis que satisfaz a fórmula: x =
False, y = True e z = True.
Note que a técnica de Backtracking nos permite encontrar uma solução para o problema SAT da
fórmula de forma sistemática, testando todas as possibilidades de atribuição de valores às variáveis.
No entanto, para fórmulas mais complexas, o tempo de execução pode ser muito grande e outras
técnicas, como a Programação Dinâmica, podem ser mais eficientes.
Nessa árvore, cada nó representa uma escolha de valor para
uma das variáveis da fórmula (x, y ou z). Os nós que levam à
solução do problema estão marcados como "Solution
Found". Os nós que levam a um beacktracking indicam que
o valor escolhido para a variável não leva a uma solução e,
portanto, precisamos voltar atrás e escolher outro valor
para uma variável anterior. Note que a árvore de decisão
tem profundidade 3, pois temos 3 variáveis na fórmula.
9. É dada uma peça retangular de tecido com dimensões X
x Y, onde X e Y são inteiros positivos, e uma lista de n produtos que podem ser feitos usando o
tecido. Para cada produto i ∈ [1, n] você sabe que um retângulo de tecido de dimensões a i x bi é
necessário, e que o preço final de venda do produto é c i. Considere que ai, bi e ci são todos inteiros
positivos. Você tem uma máquina que pode cortar qualquer peça retangular de pano em duas
peças, horizontal ou verticalmente. É possível aplicar programação dinâmica para o projeto de um
algoritmo que determine o melhor retorno possível sobre a peça de tecido de X x Y, ou seja, uma
estratégia para cortar o tecido de forma que os produtos feitos das peças resultantes deem a soma
máxima de preços de venda? Justifique.
Sim, pois o princípio da otimalidade é aplicável ao contexto e os subproblemas são superpostos.
Afinal, o custo ótimo de cortar uma peça retangular de tecido é a soma dos custos ótimos de cortar
2 partes da peça retangular (e assim por diante).

Você também pode gostar