Você está na página 1de 58

Introdução à Computação II

5954006

7. Outros Paradigmas de
Projeto de Algoritmos

Prof. Renato Tinós

Depto. de Computação e Matemática


(FFCLRP/USP)
Introdução à Computação II – 5954006 1
Principais Tópicos

7.1. Algoritmos Exaustivos


7.2. Algoritmos Gulosos
7.3. Programação Dinâmica

Introdução à Computação II – 5954006 2


7.1. Algoritmos Exaustivos

• A recursividade pode ser usada para a resolução


de problemas em que todas as alternativas
possíveis devem ser exploradas

• Este procedimento é empregado pelos


Algoritmos Exaustivos (ou Algoritmos
Tentativa e Erro) nos quais
 O processo é decomposto em um número finito de
subtarefas parciais
 As subtarefas são exploradas exaustivamente

Introdução à Computação II – 5954006 3


7.1. Algoritmos Exaustivos
• Percurso do Cavalo de Xadrez
 É possível o cavalo percorrer todo o tabuleiro, tal
que todas as células sejam percorridas
exatamente uma vez?
 O cavalo deve se mover segundo as regras do
jogo de xadrez...

Introdução à Computação II – 5954006 4


7.1. Algoritmos Exaustivos

• Percurso do Cavalo de Xadrez

Introdução à Computação II – 5954006 5


7.1. Algoritmos Exaustivos

• Percurso do Cavalo de Xadrez

Introdução à Computação II – 5954006 6


7.1. Algoritmos Exaustivos

• Percurso do Cavalo de Xadrez

Introdução à Computação II – 5954006 7


7.1. Algoritmos Exaustivos

• Percurso do Cavalo de Xadrez

Introdução à Computação II – 5954006 8


7.1. Algoritmos Exaustivos

• Percurso do Cavalo de Xadrez

Introdução à Computação II – 5954006 9


7.1. Algoritmos Exaustivos

• Percurso do Cavalo de Xadrez

Introdução à Computação II – 5954006 10


7.1. Algoritmos Exaustivos

• Percurso do Cavalo de Xadrez

Introdução à Computação II – 5954006 11


7.1. Algoritmos Exaustivos

• Percurso do Cavalo de Xadrez

Introdução à Computação II – 5954006 12


7.1. Algoritmos Exaustivos

• Percurso do Cavalo de Xadrez

Introdução à Computação II – 5954006 13


7.1. Algoritmos Exaustivos

• Percurso do Cavalo de Xadrez


 Considere que o tamanho do tabuleiro pode
variar

N colunas

Introdução à Computação II – 5954006 14


7.1. Algoritmos Exaustivos
Algoritmo TenteProximoMovimento()
iniciar seleção dos movimentos
faça
selecionar o próximo candidato da lista de movimentos
se (aceitável)
registrar movimento
se (tabuleiro não preenchido completamente)
TenteProximoMovimento()
se (insucesso)
eliminar movimento
fim se
fim se
fim se
enquanto (movimento sem sucesso && há mais candidatos)

Introdução à Computação II – 5954006 15


7.1. Algoritmos Exaustivos

• 1ª Versão: Refinamentos

 O tabuleiro será representado por uma matriz


de inteiros na qual os índices utilizados
variam de 1 até o número de linhas/colunas,
ou seja, h[1..8][1..8]

sendo:
h[x][y] = 0 indica que a célula (x,y) não foi ocupada
h[x][y] = i indica que a célula (x,y) foi ocupada no
movimento i (1 ≤ i ≤ n2)
n indica o tamanho do tabuleiro (número de linhas ou
colunas)
Introdução à Computação II – 5954006 16
7.1. Algoritmos Exaustivos

• Parâmetros do procedimento
 (x,y) : coordenadas onde o cavalo se encontra
 i : número do movimento (para fins de registro)
 sucesso : variável Booleana que indica que o movimento
teve sucesso

• (u,v) serão duas variáveis locais que representam


as coordenadas dos possíveis pontos de destino
dos movimentos, determinados conforme a lei de
movimentação do cavalo

Introdução à Computação II – 5954006 17


7.1. Algoritmos Exaustivos

• “tabuleiro não preenchido completamente”


 i < n2
• “aceitável”
 1 ≤ u ≤ n e 1 ≤ v ≤ n e h[u][v] = 0
• “registrar movimento”
 h[u][v] = i
• “eliminar movimento”
 h[u][v] = 0
Introdução à Computação II – 5954006 18
7.1. Algoritmos Exaustivos
Algoritmo TenteProximoMovimento( i , x , y , &s )
iniciar seleção dos movimentos
sucesso 0
faça
seja (u,v) o ponto de destino do próximo movimento
se ( ( 1 ≤ u ) e ( u ≤ n ) e ( 1 ≤ v ) e ( v ≤ n ) e ( h[u][v] = 0 ) )
h[u][v]  i // registrar movimento
se ( i < n*n )
TenteProximoMovimento(i+1 , u , v, sucesso);
se ( sucesso= 0 )
h[u][v]  0 // eliminar movimento
fim se
senão
sucesso  1
fim se
fim se
enquanto ( (sucesso = 0 ) e (há mais candidatos) )
s  sucesso Introdução à Computação II – 5954006 19
7.1. Algoritmos Exaustivos

• Até o momento, o
programa foi 3 2
desenvolvido de maneira
completamente 4 1
independente das regras
que regem os
movimentos do cavalo
• Dado um par de 5 8
coordenadas (x,y),
existem oito possíveis 6 7
células candidatas (u,v)
de destino
Introdução à Computação II – 5954006 20
7.1. Algoritmos Exaustivos

• Movimentos Possíveis
 (x,y) = posição atual
 (u,v) = nova posição
3 2
 1: (x+2,y+1)
4 1
 2: (x+1,y+2)
 3: (x-1,y+2) y
 4: (x-2,y+1)
 5: (x-2,y-1)
5 8
 6: (x-1,y-2)
6 7
 7: (x+1,y-2)
 8: (x+2,y-1) x
Introdução à Computação II – 5954006 21
7.1. Algoritmos Exaustivos

• Um método simples para obter (u,v) a partir de (x,y) é


através da adição de diferenças de coordenadas, que serão
armazenadas nos vetores dx e dy, que serão iniciados com
valores apropriados
• Um índice k será utilizado para numerar o próximo
candidato
• O procedimento recursivo é iniciado por uma chamada,
tendo como parâmetros as coordenadas iniciais (i,j)
fornecidas pelo usuário; a esta posição no tabuleiro deve
ser atribuído o valor 1:
 h[i][j] = 1;
 TenteProximoMovimento(2,i,j,q);

Introdução à Computação II – 5954006 22


7.1. Algoritmos Exaustivos
#include <iostream> void TryNextMove(int i,int x,int y,bool &s)
#include <iomanip> { int u,v,k;
using namespace std; bool sucesso;

const int Size = 8; // tamanho maximo k = 0;


int dx[Size+1] = {0,2,1,-1,-2,-2,-1,1,2}, sucesso = false;
dy[Size+1] = {0,1,2,2,1,-1,-2,-2,-1}, do
h[Size+1][Size+1], { k++;
n; u = x + dx[k];
v = y + dy[k];
//---------------------------------------- if (1<=u && u<=n && 1<=v && v<=n &&
void Print() h[u][v]==0)
{ int i,j; { h[u][v] = i;
if (i < n*n)
for(i=1; i<=n; i++) { TryNextMove(i+1,u,v,sucesso);
{ for(j=1; j<=n; j++) if (!sucesso)
cout << setw(5) << h[i][j]; h[u][v] = 0;
cout << endl; }
} else
cout << endl; sucesso = true;
} }
//---------------------------------------- } while (!sucesso && k < Size);
s = sucesso;
}

Introdução à Computação II – 5954006 23


7.1. Algoritmos Exaustivos
int main() Tamanho do tabuleiro (1-8): 5
{ int i,j; Posicao inicial do cavalo (x,y): 3 3

bool q; 23 10 15 4 25
16 5 24 9 14
11 22 1 18 3
cout << "Tamanho do tabuleiro (1-8): "; 6 17 20 13 8
cin >> n; 21 12 7 2 19

for(i=1; i<=n; i++)


Tamanho do tabuleiro (1-8): 5
for(j=1; j<=n; j++)
Posicao inicial do cavalo (x,y): 4 2
h[i][j] = 0; 23 10 13 4 21
cout << "Posicao inicial do cavalo (x,y): "; 12 5 22 9 14
cin >> i >> j; 17 24 11 20 3
6 1 18 15 8
h[i][j] = 1;
25 16 7 2 19
TryNextMove(2,i,j,q);
if (q) Tamanho do tabuleiro (1-8): 6
Print(); Posicao inicial do cavalo (x,y): 1 1
1 16 7 26 11 14
else
34 25 12 15 6 27
cout << "Caminho nao encontrado" << endl; 17 2 33 8 13 10
return 0; 32 35 24 21 28 5
} 23 18 3 30 9 20
36 31 22 19 4 29

Introdução à Computação II – 5954006 24


7.1. Algoritmos Exaustivos

• Exemplo de percurso

23 10 15 4 25

16 5 24 9 14

11 22 1 18 3

6 17 20 13 8

21 12 7 2 19
Introdução à Computação II – 5954006 25
7.1. Algoritmos Exaustivos

• O algoritmo visto anteriormente é um exemplo de


um algoritmo exaustivo
• O padrão característico de um algoritmo exaustivo
é que
 passos próximos da solução total são
 obtidos e armazenados para uso futuro
 eliminados da memorização quando se descobre que o passo
corrente não terá, seguramente, nenhuma possibilidade de
conduzir à solução total procurada,
 o passo levará a um beco sem saída

• Esta característica é conhecida como backtracking


Introdução à Computação II – 5954006 26
7.1. Algoritmos Exaustivos
Algoritmo Backtracking()
iniciar seleção de candidatos
faça
próxima seleção
se (aceitável)
armazenar
se (solução incompleta)
Backtracking()
se ( sem sucesso)
cancelar seleção
fim se
fim se
fim se
enquanto ( (sem sucesso) e (há mais candidatos) )

Introdução à Computação II – 5954006 27


7.1. Algoritmos Exaustivos

• Na prática, os programas assumem diversos


padrões, derivados do padrão geral
• Uma forma padrão usualmente encontrada utiliza
um parâmetro explícito, que indica o grau de
profundidade de recursão e que permite a utilização
de uma condição simples de término
• Se, além disso, em cada passo o número de
candidatos a serem avaliados for fixo (por exemplo,
m), então o padrão seguinte é aplicável, sendo
ativado pelo comando Backtracking2(1)

Introdução à Computação II – 5954006 28


7.1. Algoritmos Exaustivos
Algoritmo Backtracking2( i )
k 0
faça
kk+1
selecionar o k-ésimo candidato
se (aceitável)
armazenar
se ( i < n )
Backtracking2( i+1 )
se ( sem sucesso)
cancelar seleção
fim se
fim se
fim se
enquanto ( (sem sucesso) e ( k < m ) )
Introdução à Computação II – 5954006 29
7.1. Algoritmos Exaustivos

• O problema das oito rainhas


 Suponha que você tenha
 8 rainhas de um jogo de xadrez
um tabuleiro de xadrez

Introdução à Computação II – 5954006 30


7.1. Algoritmos Exaustivos

• O problema das oito rainhas


 As rainhas podem ser dispostas no tabuleiro de
modo que duas rainhas não se ataquem?

Introdução à Computação II – 5954006 31


7.1. Algoritmos Exaustivos

• O problema das oito rainhas


 Duas rainhas não podem ficar na mesma linha...

Introdução à Computação II – 5954006 32


7.1. Algoritmos Exaustivos

• O problema das oito rainhas


 Duas rainhas não podem ficar na mesma linha,
ou na mesma coluna...

Introdução à Computação II – 5954006 33


7.1. Algoritmos Exaustivos

• O problema das oito rainhas


 Duas rainhas não são podem ficar na mesma
linha, ou na mesma coluna, ou na mesma
diagonal

Introdução à Computação II – 5954006 34


7.1. Algoritmos Exaustivos

• Generalizando
 O problema das N rainhas N Rainhas

N colunas

Introdução à Computação II – 5954006 35


7.1. Algoritmos Exaustivos
Algoritmo nRainhas( i )
iniciar seleção de posição para a selecionar a i-ésima rainha
faça
executar próxima seleção
se (rainha está salva)
posicionar rainha
se ( i < n )
nRainhas( i + 1 )
se ( sem sucesso)
remover rainha
fim se
fim se
fim se
enquanto ( (sem sucesso) e ( há mais posições ) )
Introdução à Computação II – 5954006 36
7.1. Algoritmos Exaustivos

• A rainha ataca peças que se encontrem na


mesma linha, coluna ou diagonal do tabuleiro
 Cada coluna deve conter uma e só uma rainha
 A escolha da posição da i-ésima rainha deve
restringir-se às casas da i-ésima coluna
• O parâmetro i é o índice da coluna
• A escolha da linha j limita-se a escolher uma
dentre as n linhas disponíveis (1 ≤ j ≤ n)

Introdução à Computação II – 5954006 37


7.1. Algoritmos Exaustivos

• Cada vez que o


programa coloca uma
rainha no tabuleiro, sua i
posição é guardada em
x[i]

Introdução à Computação II – 5954006 38


7.1. Algoritmos Exaustivos

• Cada vez que o


programa coloca uma
rainha no tabuleiro, sua i
posição é guardada em
x[i]
• Uma nova chamada
recursiva é efetuada,
nRainhas(i+1)

Introdução à Computação II – 5954006 39


7.1. Algoritmos Exaustivos

• Cada vez que o


programa coloca uma
rainha no tabuleiro, sua
posição é guardada em
i
x[i]
• Uma nova chamada
recursiva é efetuada,
nRainhas(i+1),
iniciando outro nível de
recursão...

Introdução à Computação II – 5954006 40


7.1. Algoritmos Exaustivos

• Se há conflito o
programa muda a nova
rainha para a próxima
coluna à direita
i

Introdução à Computação II – 5954006 41


7.1. Algoritmos Exaustivos

• Quando não há mais


conflitos o programa
tenta colocar a próxima
rainha no tabuleiro,
i
ativando nRainhas(i+1)

Introdução à Computação II – 5954006 42


7.1. Algoritmos Exaustivos

• Vamos olhar na
terceira linha. A
primeira posição que
tentamos tem um
conflito...
i

Introdução à Computação II – 5954006 43


7.1. Algoritmos Exaustivos

• Vamos olhar na
terceira linha. A
primeira posição que
tentamos tem um
conflito...
• ...então mudamos para i
a coluna 2. Mas outro
conflito surge...

Introdução à Computação II – 5954006 44


7.1. Algoritmos Exaustivos

• Vamos olhar na
terceira linha. A
primeira posição que
tentamos tem um
conflito...
• ...então mudamos para i
a coluna 2. Mas outro
conflito surge...
• ...e mudamos para a
terceira coluna. Ainda
há conflito...
Introdução à Computação II – 5954006 45
7.1. Algoritmos Exaustivos

• Vamos olhar na terceira linha. A


primeira posição que tentamos
tem um conflito...
• ...então mudamos para a coluna
2. Mas outro conflito surge...
• ...e mudamos para a terceira
coluna. Ainda há conflito...
• ...e mudamos para a quarta i
coluna, ainda há conflito...
• ...e não existem mais colunas
disponíveis!!!

Introdução à Computação II – 5954006 46


7.1. Algoritmos Exaustivos

• Quando não há mais


espaço em uma linha,
o algoritmo retorna
para a recursão de
i
nível anterior, ou seja,
do nível 3 para o 2

Introdução à Computação II – 5954006 47


7.1. Algoritmos Exaustivos

• Quando não há mais


espaço em uma linha,
o algoritmo retorna
para a recursão de
i
nível anterior, ou seja,
do nível 3 para o 2
• ...e continua
trabalhando na linha 2,
mudando a rainha para
a direita

Introdução à Computação II – 5954006 48


7.1. Algoritmos Exaustivos

• Essa posição não


apresenta conflitos,
então podemos ativar o
próximo nível de
i
recursão, nRainhas(i+1)

Introdução à Computação II – 5954006 49


7.1. Algoritmos Exaustivos

• Na linha 3, começamos
novamente pela
primeira coluna,
reiniciando todo o
processo
i

Introdução à Computação II – 5954006 50


7.1. Algoritmos Exaustivos

• Implementação

 A escolha óbvia para representar as rainhas no


tabuleiro é uma matriz quadrada
 Entretanto, esta escolha acarretaria a necessidade de
operações exaustivas para a verificação de
disponibilidade de posições

 Assim, representaremos tão diretamente quanto


possível a informação que for realmente relevante
e utilizada com freqüência
 Não é o caso da posição das rainhas mas sim se a rainha
já tenha sido colocada corretamente em uma dada
posição (em uma linha, coluna ou diagonal)
 Note que somente uma rainha deve ser colocada em
cada coluna k (1 ≤ k ≤ i ) Introdução à Computação II – 5954006 51
7.1. Algoritmos Exaustivos

• int x[1..8]
 x[i] indica a posição da rainha da i-ésima coluna
• bool a[1..8]
 a[j] significa “nenhuma rainha está na j-ésima coluna”
• bool b[2..16]
 b[k] significa “nenhuma rainha ocupa a k-ésima diagonal
do tipo / ”
 k=i+j

Introdução à Computação II – 5954006 52


7.1. Algoritmos Exaustivos
• bool c[2..16]
 c[r] significa “nenhuma rainha ocupa a r-ésima
diagonal do tipo \ ”
 r = i – j (-7 <= r <= 7, índice assume valores
negativos)
 r = i – j + 9 (2 <= r <= 16)

Introdução à Computação II – 5954006 53


7.1. Algoritmos Exaustivos

• “posicionar rainha” 1 2 3 4 5 6 7 8
 x[i] = j

1 2 3 4
 a[j] = false
 b[i+j] = false
 c[i-j+9] = false
• “remover rainha”
5 6
 a[j] = true
 b[i+j] = true
 c[i-j+9] = true
7 8

• “rainha está salva”


 a[j] e b[i+j] e c[i-j+9]

Introdução à Computação II – 5954006 54


7.1. Algoritmos Exaustivos
#include <iostream> void Try(int i, bool &s)
#include <iomanip> { int j;
using namespace std;
j = 0;
bool a[9],b[17],c[17]; s = false;
int n,x[9]; do
{ j++;
void Print() if (a[j] && b[i+j] && c[i-j+9])
{ int i; { x[i] = j;
a[j]=b[i+j]=c[i-j+9]=false;
for(i=1; i<=n; i++) if (i < n)
cout << "(" << i { Try(i+1,s);
<< "," << x[i] if (!s)
<< ") "; a[j]=b[i+j]=c[i-j+9]=true;
cout << endl; }
} else
s = true;
}
} while (!s && j < n);
}

Introdução à Computação II – 5954006 55


7.1. Algoritmos Exaustivos

int main()
{ int i;
bool q;

cout << "Tamanho do tabuleiro (1-8): ";


cin >> n;
for(i=1; i<=8; i++)
a[i] = true;
for(i=2; i<=16; i++)
{ b[i] = true;
c[i] = true;
}
Try(1,q);
if (q)
Print();
else
"Nao foi possivel posicionar as rainhas" << endl;
return 0;
}

Introdução à Computação II – 5954006 56


7.1. Algoritmos Exaustivos
• Oito Rainhas: As Doze Soluções
x1 x2 x3 x4 x5 x6 x7 x8
1 5 8 6 3 7 2 4
1 6 8 3 7 4 2 5
1 7 4 6 8 2 5 3
1 7 5 8 2 4 6 3
2 4 6 8 3 1 7 5
2 5 7 1 3 8 6 4
2 5 7 4 1 8 6 3
2 6 1 7 4 8 3 5
2 6 8 3 1 4 7 5
2 7 3 6 8 5 1 4
2 7 5 8 1 4 6 3
2 8 6 1 3 5 7 4
Introdução à Computação II – 5954006 57
Comentários

• Copyright
 Parte do material desta apresentação foi
obtida através de slides da disciplina de
Introdução à Computação II ministrada
pelo Prof. José Augusto Baranauskas

Introdução à Computação II – 5954006 58

Você também pode gostar