Buscar

Backtracking: Oito Rainhas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 3, do total de 34 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 6, do total de 34 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 9, do total de 34 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Prévia do material em texto

MC202-Estruturas de Dados
Luiz E. Buzato
Instituto de Computação – UNICAMP
buzato@ic.unicamp.br
sala 16, IC 01
2S2010
Tópico: Retrocesso (Backtracking)
Oito Rainhas
Enunciado
Posicione oito rainhas em um tabuleiro de xadrez (8 × 8) de forma
que nenhuma seja capaz de capturar qualquer outra utilizando os
movimentos posśıveis de uma rainha do jogo de xadrez.
Oito Rainhas
Enunciado
Posicione oito rainhas em um tabuleiro de xadrez (8 × 8) de forma
que nenhuma seja capaz de capturar qualquer outra utilizando os
movimentos posśıveis de uma rainha do jogo de xadrez.
O problema geral consiste em posicionar n rainhas em um tabuleiro
n× n de forma a garantir que nenhuma pode tomar qualquer outra.
Oito Rainhas
Uma configuração que resolve o problema
0Z0L0Z0Z
Z0Z0Z0L0
0ZQZ0Z0Z
Z0Z0Z0ZQ
0L0Z0Z0Z
Z0Z0L0Z0
QZ0Z0Z0Z
Z0Z0ZQZ0
Oito Rainhas
Uma configuração que resolve o problema
0Z0L0Z0Z
Z0Z0Z0L0
0ZQZ0Z0Z
Z0Z0Z0ZQ
0L0Z0Z0Z
Z0Z0L0Z0
QZ0Z0Z0Z
Z0Z0ZQZ0
Quantas existem?
Rainhas (n = 4)
4 × 4
Possibilidades: 16 posições no total, devemos escolher 4.
(
16
4
)
=
16!
4!(16 − 4)!
= 21621600
Soluções: 2 (distintas: 1).
Solução: Força Bruta
Enumeração exaustiva
É posśıvel, mas ineficiente.
Uma solução mais interessante
O que queremos?
Queremos uma função que retorne o conjunto de configurações,
digamos A, que resolve o problema.
Uma Estratégia
Busque um conjunto B de configurações que satisfaça as seguintes
propriedades:
1. A ⊂ B;
2. dado um elemento de B, não deve ser muito dif́ıcil decidir se
ele também pertence a A;
3. escrever a função que gera todos os elementos de B deve ser
simples.
A Solução Geral
Com a ajuda da função escrita no passo 3. da estratégia, enumere
os elementos de B e submeta-os, uma a um, ao critério de decisão
definido no passo 2. A execução do critério de decisão determina
quais elementos de B devem ser descartados e quais devem ser
retornados como um configuração boa, isto é, a configuração é um
elemento de A. Graças a 1. temos uma solução para o problema.
Observações importantes
1. Para que a estratégia faça sentido, B não pode ser idêntico a
A e como B deve conter A, então B deve ser maior que A.
Por razão de eficiência, entretanto, é aconselhável escolher B
tão pequeno quanto posśıvel.
2. Devemos escolher um critério de decisão que seja fácil de
aplicar. Pelo menos o fato de que um elemento de B não
pertencer a A deve ser fácil de testar.
3. No final, a estratégia é interessante, porque supõe que a
geração dos elementos de B é mais simples que a geração dos
elementos de A. É claro que se essa condição não for
verdadeira, podemos sempre pensar recursivamente!
Procura-se um conjunto C que contém B como um
subconjunto, etc.
Um otimista tenta encontrar B
Racioćınio do otimista
Listarei todas as condições mutuamente independentes que os
elementos do conjunto A devem satisfazer e suprimirei uma delas.
Usarei as que sobrarem para gerar B.
Um otimista tenta encontrar B
A pode ser caracterizado por:
1. há 8 rainhas no tabuleiro;
2. quaisquer 2 delas não podem se enfrentar;
Que Bs o otimista encontra?
B1 todas as configurações de 8 rainhas no tabuleiro tal que
quaisquer duas não podem se enfrentar.
B2 todas as configurações de 8 rainhas no tabuleiro.
Esse conjuntos são muito grandes! O otimista não obteve o
resultado que esperava.
Como encontrar B?
Uma estratégia menos otimista pede que listemos as propriedades
construtivas de uma configuração que é um elemento de B.
Construção de B
(a) Nenhuma coluna pode conter mais de uma rainha. Como
devemos posicionar 8 rainhas, sabemos que cada linha conterá
exatamente 1 rainha.
(b) Analogamente, conclúımos que cada coluna conterá
exatamente uma rainha.
(c) Há 15 diagonais para cima (ր) cada uma contendo
exatamente 1 rainha, isto é, 8 diagonais contém rainhas, uma
por diagonal, e 7 diagonais estão vazias.
Construção de B
(d) Há 15 diagonais para baixo (ց), cada uma contendo
exatamente 1 rainha.
(e) Dada qualquer configuração não vazia de rainhas tal que duas
a duas elas não podem se enfrentar, a remoção de qualquer
uma delas resultará em uma configuração com a mesma
propriedade.
A propriedade (e) é muito importante
0Z0L0Z0Z
Z0Z0Z0L0
0ZQZ0Z0Z
Z0Z0Z0ZQ
0L0Z0Z0Z
Z0Z0L0Z0
QZ0Z0Z0Z
Z0Z0ZQZ0
A propriedade (e) é muito importante
0Z0L0Z0Z
Z0Z0Z0L0
0ZQZ0Z0Z
Z0Z0Z0ZQ
0L0Z0Z0Z
Z0Z0L0Z0
QZ0Z0Z0Z
Z0Z0Z0Z0
A propriedade (e) é muito importante
0Z0L0Z0Z
Z0Z0Z0L0
0ZQZ0Z0Z
Z0Z0Z0ZQ
0L0Z0Z0Z
Z0Z0L0Z0
0Z0Z0Z0Z
Z0Z0Z0Z0
A propriedade (e) é muito importante
0Z0L0Z0Z
Z0Z0Z0L0
0ZQZ0Z0Z
Z0Z0Z0ZQ
0L0Z0Z0Z
Z0Z0Z0Z0
0Z0Z0Z0Z
Z0Z0Z0Z0
A propriedade (e) é muito importante
0Z0L0Z0Z
Z0Z0Z0L0
0ZQZ0Z0Z
Z0Z0Z0ZQ
0Z0Z0Z0Z
Z0Z0Z0Z0
0Z0Z0Z0Z
Z0Z0Z0Z0
A propriedade (e) é muito importante
0Z0L0Z0Z
Z0Z0Z0L0
0ZQZ0Z0Z
Z0Z0Z0Z0
0Z0Z0Z0Z
Z0Z0Z0Z0
0Z0Z0Z0Z
Z0Z0Z0Z0
A propriedade (e) é muito importante
0Z0L0Z0Z
Z0Z0Z0L0
0Z0Z0Z0Z
Z0Z0Z0Z0
0Z0Z0Z0Z
Z0Z0Z0Z0
0Z0Z0Z0Z
Z0Z0Z0Z0
A propriedade (e) é muito importante
0Z0L0Z0Z
Z0Z0Z0Z0
0Z0Z0Z0Z
Z0Z0Z0Z0
0Z0Z0Z0Z
Z0Z0Z0Z0
0Z0Z0Z0Z
Z0Z0Z0Z0
A propriedade (e) é muito importante
0Z0Z0Z0Z
Z0Z0Z0Z0
0Z0Z0Z0Z
Z0Z0Z0Z0
0Z0Z0Z0Z
Z0Z0Z0Z0
0Z0Z0Z0Z
Z0Z0Z0Z0
A propriedade (e) é muito importante
Construção de configurações em B
0Z0Z0Z0Z
Z0Z0Z0Z0
0Z0Z0Z0Z
Z0Z0Z0Z0
0Z0Z0Z0Z
Z0Z0Z0Z0
0Z0Z0Z0Z
Z0Z0Z0Z0
A propriedade (e) é muito importante
Construção de configurações em B
0Z0L0Z0Z
Z0Z0Z0Z0
0Z0Z0Z0Z
Z0Z0Z0Z0
0Z0Z0Z0Z
Z0Z0Z0Z0
0Z0Z0Z0Z
Z0Z0Z0Z0
A propriedade (e) é muito importante
Construção de configurações em B
0Z0L0Z0Z
Z0Z0Z0L0
0Z0Z0Z0Z
Z0Z0Z0Z0
0Z0Z0Z0Z
Z0Z0Z0Z0
0Z0Z0Z0Z
Z0Z0Z0Z0
A propriedade (e) é muito importante
Construção de configurações em B
0Z0L0Z0Z
Z0Z0Z0L0
0ZQZ0Z0Z
Z0Z0Z0Z0
0Z0Z0Z0Z
Z0Z0Z0Z0
0Z0Z0Z0Z
Z0Z0Z0Z0
A propriedade (e) é muito importante
Construção de configurações em B
0Z0L0Z0Z
Z0Z0Z0L0
0ZQZ0Z0Z
Z0Z0Z0ZQ
0Z0Z0Z0Z
Z0Z0Z0Z0
0Z0Z0Z0Z
Z0Z0Z0Z0
A propriedade (e) é muito importante
Construção de configurações em B
0Z0L0Z0Z
Z0Z0Z0L0
0ZQZ0Z0Z
Z0Z0Z0ZQ
0L0Z0Z0Z
Z0Z0Z0Z0
0Z0Z0Z0Z
Z0Z0Z0Z0
A propriedade (e) é muito importante
Construção de configurações em B
0Z0L0Z0Z
Z0Z0Z0L0
0ZQZ0Z0Z
Z0Z0Z0ZQ
0L0Z0Z0Z
Z0Z0L0Z0
0Z0Z0Z0Z
Z0Z0Z0Z0
A propriedade (e) é muito importante
Construção de configurações em B
0Z0L0Z0Z
Z0Z0Z0L0
0ZQZ0Z0Z
Z0Z0Z0ZQ
0L0Z0Z0Z
Z0Z0L0Z0
QZ0Z0Z0Z
Z0Z0Z0Z0
A propriedade (e) é muito importante
Construção de configurações em B
0Z0L0Z0Z
Z0Z0Z0L0
0ZQZ0Z0Z
Z0Z0Z0ZQ
0L0Z0Z0Z
Z0Z0L0Z0
QZ0Z0Z0Z
Z0Z0ZQZ0
B1 novamente
Haviamos rejeitado B1 porque ele era muito grande. Mas se
utilizarmos a liberdade que a propriedade (e) nos oferece de
construção incremental, adiciona-se uma rainha por vez, e
sistemática, a rainha é adicionada sempre de acordo com as regras
simples de (a) a (f), de uma configuração de B1, então o número
de configurações a ser gerado diminúı e temos uma forma simples
de gerar uma nova configuração a partir da que já temos.
De B1 para B
Em que ordem devemos gerar os elementos de B1?
Uma outra questão relacionada a esta é como descrevemos uma
configuração?
Descrição (Caracterização) de uma configuração
Numeraremos as linhas e colunas do tabuleiro de 0 a 7.
Graças à propriedade (a) podemos ordenar as rainhas de acordo
com o número da linha que ocupam. Isto induz a declaração da
seguinte estrutura:
i n t c o n f i g u r a t i o n [ 8 ] ;
configuration[i] contém o número da coluna ocupada pela
rainha da linha i .
Caractericação de configurações
Uma configuração é uma “palavra” de 8 digitos e uma ordem bem
razoável para a geração dessas “palavras” é em ordem alfabética.
Conclusão: Gera-se os elementos de B em ordem alfabética e,
conseqüentemente, os elementos de A nessa mesmaordem.
Backtracking
0Z0Z0Z0Z
Z0Z0Z0Z0
0Z0Z0Z0Z
Z0Z0Z0Z0
0Z0Z0Z0Z
Z0Z0Z0Z0
0Z0Z0Z0Z
Z0Z0Z0Z0
Backtracking
QZ0Z0Z0Z
Z0Z0Z0Z0
0Z0Z0Z0Z
Z0Z0Z0Z0
0Z0Z0Z0Z
Z0Z0Z0Z0
0Z0Z0Z0Z
Z0Z0Z0Z0
Backtracking
QZ0Z0Z0Z
Z0L0Z0Z0
0Z0Z0Z0Z
Z0Z0Z0Z0
0Z0Z0Z0Z
Z0Z0Z0Z0
0Z0Z0Z0Z
Z0Z0Z0Z0
Backtracking
QZ0Z0Z0Z
Z0L0Z0Z0
0Z0ZQZ0Z
Z0Z0Z0Z0
0Z0Z0Z0Z
Z0Z0Z0Z0
0Z0Z0Z0Z
Z0Z0Z0Z0
Backtracking
QZ0Z0Z0Z
Z0L0Z0Z0
0Z0ZQZ0Z
ZQZ0Z0Z0
0Z0Z0Z0Z
Z0Z0Z0Z0
0Z0Z0Z0Z
Z0Z0Z0Z0
Backtracking
QZ0Z0Z0Z
Z0L0Z0Z0
0Z0ZQZ0Z
ZQZ0Z0Z0
0Z0L0Z0Z
Z0Z0Z0Z0
0Z0Z0Z0Z
Z0Z0Z0Z0
Backtracking
QZ0Z0Z0Z
Z0L0Z0Z0
0Z0ZQZ0Z
ZQZ0Z0Z0
0Z0Z0Z0L
Z0Z0Z0Z0
0Z0Z0Z0Z
Z0Z0Z0Z0
Backtracking
QZ0Z0Z0Z
Z0L0Z0Z0
0Z0ZQZ0Z
ZQZ0Z0Z0
0Z0Z0Z0Z
Z0Z0Z0Z0
0Z0Z0Z0Z
Z0Z0Z0Z0
Backtracking
QZ0Z0Z0Z
Z0L0Z0Z0
0Z0ZQZ0Z
Z0Z0Z0L0
0Z0Z0Z0Z
Z0Z0Z0Z0
0Z0Z0Z0Z
Z0Z0Z0Z0
Backtracking
QZ0Z0Z0Z
Z0L0Z0Z0
0Z0ZQZ0Z
Z0Z0Z0L0
0Z0L0Z0Z
Z0Z0Z0Z0
0Z0Z0Z0Z
Z0Z0Z0Z0
Backtracking
E assim por diante...
Conceitos fundamentais
• espaço de soluções: conjunto de todas as tuplas que satisfaz
as restrições expĺıcitas.
• estados: conjunto de todas as subseqüências das tuplas do
espaço de soluções.
• algoritmo força bruta: enumera todas as tuplas do espaço de
soluções e verifica quais delas satisfazem as restrições
implicitas.
• algoritmo de backtracking:
• busca sistemática no espaço de estados do problema,
organizado segundo uma estrutura de árvore, chamada árvore
do espaço de estados.
• uso de funções limitantes para restringir a busca na árvore.
Tipicamente estas funções reduzem os doḿınios das variáveis
de acordo com as decisões anteriores.
Conceitos fundamentais
• Onde usar?
• Problemas cujas soluções são caracterizadas por uma
seqüência de decisões, cada uma delas feita sobre um conjunto
de várias possibilidades.
• Soluções são representadas por tuplas (vetores) de tamanho
fixo ou variável da forma (x1, . . . , xn).
• uma tupla é dita viável se ela atende ao conjunto de restrições
expĺıcitas e impĺıcitas que definem o problema.
• Solucionar o problema equivale a encontrar uma (ou toda)
tupla viável.
• Restrições:
• Expĺıcitas: definem os doḿınios das váriaves na tupla.
• Impĺıcitas: relações entre as variáveis da tupla que especificam
quais delas respondem ao problema.
Conceitos fundamentais
Origem do nome: backtracking
Durante a execução de um algoritmo de backtracking, pode-se
chegar a um estado cuja seqüência de decisões torna vazio o
doḿınio de uma variável da tupla sem que as restrições implicitas
tenham sido satisfeitas.
Neste caso, o algoritmo retrocede (≡ faz um backtracking),
revertendo a última decisão tomada e escolhendo um novo valor do
doḿınio para uma variável correspondente a ela. Se todas as
posśıveis escolhas tiverem sido tentadas, o algoritmo retrocede
novamente.
Encontramos B
• São todos os elementos de B1 com uma rainha em cada linha
tal que quaisquer duas rainhas não podem se enfrentar.
• Para saber se uma configuração pertence a A basta testar se
n = 8.
Codificação: 1
i n i c i a T a b u l e i r o ( ) ;
do
geraProxElemDeB ( ) ;
i f ( n==8) impr imeCon f i gu racao ( ) ;
whi le ( BNaoForVazio ( ) ) ;
Codificação: 1
A codificação 1 não é muito intessante porque não detalha
geraProxElemDeB(). Vamos melhorá-la.
Codificação: 2
i n i c i a T a b u l e i r o ( ) ;
pos = 0 ;
do
co l oque r a i n h a em t a b u l e i r o [ 0 , pos ] ;
g e r e todas as c o n f i g u r a c o e s
com r a i n h a f i x a na po s i c a o 0 ;
remova a r a i n h a da po s i c a o t a b u l e i r o [ 0 , pos ] ;
pos++;
whi le ( pos != 8 ) ;
Codificação: 3
pos1 = 0 ;
do
i f l i v r e ( t a b u l e i r o [ 1 , pos1 ] ) {
p o s i c i o n e r a i n h a em t a b u l e i r o [ 1 , h1 ] ;
g e r e todas as c o n f i g u r a ç õ e s com r a i n h a s f i x a s
a t é aqu i ;
remova a r a i n h a de t a b u l e i r o [ 1 , pos1 ] ;
pos1++;
whi le ( pos1 != 8 ) ;
Oito dos encadeados
Se continuassemos a codificação dessa maneira teriamos 8 laços
encadeados.
Isso não é elegante, mas é instrutivo.
Mostra que dá para criar um código recursivo muito conciso e
eficiente.
Do esboço para o código completo
Variáveis
• n = o número de rainhas no tabuleiro;
• configuracao[i], 0 ≤ i < n, o número da coluna ocupada pela
rainha na i-ésima linha.
Temos as estruturas necessárias e suficientes para codificar o
algoritmo.
Mas podemos tornar o algoritmo mais simples de escrever se
definirmos algumas variávais auxiliares.
Estruturas auxiliares: 1
Uma matriz de booleanos?
A cada inserção 28 posições terão que ser verificadas.
A cada remoção a matriz terá que ser verificada.
Da para fazer melhor.
Estruturas auxiliares: 2
• Não precisamos verificar linhas: estão livres por definição.
• Precisamos verificar colunas, diagonais ր e diagonais ց.
Estruturas auxiliares: 3
• boolean col[8];
• boolean up[15];
• boolean down[15];
Estruturas auxiliares: 3
• boolean col[8];
• boolean up[15];
• boolean down[15];
Examinar o código C (próxima aula!).
Pseudo código
i n t n , k ;
i n t c o n f i g [ 8 ] ;
boo l ean c o l [ 8 ] ;
boo l ean up [ −7:+7] ; /∗ i n d i c e s ! ∗/
boo l ean down [ 1 5 ] ;
main ( ) {
n = 0 ;
f o r ( k = 0 ; k < 8 ; k++) c o l [ k ] = t r u e ;
f o r ( k = 0 ; k < 15 ; k++) {
down [ k ] = t r u e ;
up [ k ] = t r u e ;
}
gen e r a t e ( ) ;
}
Pseudo código
vo id gene r a t e ( ) { i n t h ; h = 0 ;
do
i f /∗ t a b u l e i r o [ n , h ] e s t á l i v r e : ∗/
( c o l [ h ] && up [ n−h ] && down [ n+h ] ) {
/∗ po s i c . r a i n h a em t a b u l e i r o [ n , h ] : ∗/
c o n f i g [ n ] = h ; c o l [ h ] = f a l s e ;
up [ n−h ] = f a l s e ; down [ n+h ] = f a l s e ; n++;
i f /∗ t a b u l e i r o c h e i o : ∗/ ( n == 8) {
/∗ impr ime c on f i g u r a ç ã o : ∗/
f o r ( i n t k = 0 ; k < 8 ; k++) p r i n t ( c o n f i g [ k ] ) ;
p r i n t l n ;
} e l s e
gene r a t e ( ) ;
n−−;
/∗ remove r a i n h a de t a b u l e i r o [ n , h ] : ∗/
down [ n+h ] = t r u e ; up [ n−h ] = t r u e ; c o l [ h ] = t r u e ;
}
h++;
whi le ( h < 8)
}
Projeto de Algoritmos
Técnicas
• retrocesso (backtracking);
• dividir-para-conquistar (divide-and-conquer);
• programação dinâmica;
• algoritmos de busca local;
• algoritmos gulosos.

Continue navegando