Você está na página 1de 7

4. Backtracking and Branch-and-bound So mtodos geralmente usados para a soluo de grandes instncias de problemas combinatrios difceis.

. Podem ser considerados verses melhoradas do processo de busca exaustiva que consiste em avaliar todos os possveis candidatos para obter uma soluo. Esses mtodos, ao contrrio da busca exaustiva, constroem os candidatos a soluo passo a passo e, a cada passo, o candidato avaliado; se num determinado instante esta avaliao permite concluir que aquele candidato no pode levar a uma soluo ento aquela seqncia de gerao interrompida e o processo retrocede ao passo anterior e uma nova seqncia de gerao tentada. O mtodo de branch-and-bound aplicado exclusivamente a problemas de otimizao sendo que neste caso a funo objetivo tambm utilizada no processo de interrupo (corte) da seqncia de gerao de candidatos A idia central destes mtodos utilizar algum mecanismo (em geral, uma funo de corte) para avaliar se uma determinada escolha tem alguma chance de levar a uma soluo; Caso a escolha no possa levar a uma possvel soluo ento todas as opes que incluem aquela escolha podem ser ignoradas, isto , no precisam ser avaliadas; Geralmente a operao destes mtodos modelada atravs de uma rvore representando a seqncia de gerao de candidatos Considerando esta forma de representao, o mtodo de backtracking gera a rvore adotando uma busca em profundidade (depth first) e o branch-and-bound adota a busca best-first.

4.1 Backtracking Problema das 8 rainhas

Dado um tabuleiro de xadrez (com 8x8 casas), o objetivo distribuir 8 rainhas sobre este tabuleiro de modo que nenhuma delas fique em posio de ser atacada por outra rainha. Exemplo:

Observaes: H 88 = 16777216 possibilidades de configurao O nmero de configuraes possveis pode ser reduzido observando que apenas uma rainha pode estar em cada linha. Logo, a soluo pode ser representada por um vetor Q (de inteiros) com 8 posies, sendo que Q[i] = j indica que h uma rainha na posio (i,j) do tabuleiro Neste caso h apenas 8! = 40320 possibilidades de configurao Utilizando backtracking pode-se evitar o teste de diversas configuraes que no podem levar a uma soluo

Por exemplo, suponha que j foram colocadas k-1rainhas em posies seguras nas primeiras k-1 linhas, ento para colocar a k-sima rainha necessrio obter uma posio segura na linha k Pela modelagem adotada nunca haver mais de uma rainha numa mesma linha ou numa mesma coluna Resta apenas verificar as diagonais, o que pode ser feito adotando-se o seguinte critrio: duas rainhas nas posies (l1,c1) e (l2,c2) esto numa mesma diagonal se e somente se |l1 l2| = |c1 c2 | Para ilustrar este problema acesse os endereos http://www.bhopalnet.com/eightq.htm http://homepage.tinet.ie/~pdpals/8queens.htm

Estrutura geral de um algoritmo usando Backtracking inicialize a seleo de candidatos repita selecione o prximo candidato se aceitvel ento registre a escolha se soluo no est completa ento tente o prximo {corresponde chamada recursiva} se no obteve sucesso ento cancele o registro desta escolha at obter sucesso ou no haver mais candidatos a escolher

Passeio do cavalo Dado um tabuleiro de xadrez com dimenses n n, considere o cavalo posicionado numa casa de coordenadas (x0, y0). Deseja-se obter, se existir, uma seqncia de movimentos (seguindo as regras de movimento desta pea) de modo que todas as posies do tabuleiro sejam visitadas exatamente uma nica vez. Regras de movimento do cavalo:

Posies que o cavalo pode ocupar a partir de uma dada posio

Para solucionar este problema podemos utilizar o seguinte mtodo: (a) a partir da posio corrente, selecione uma posio possvel (que ainda no foi escolhida/avaliada) (b) se a posio aceitvel, isto , se ainda no foi visitada, registre-a como posio visitada (c) se ainda h posies a visitar tente um prximo movimento a partir da posio escolhida no item (b) (d) se a posio escolhida no item (b) no levou a uma soluo, remarque a posio como no visitada (e) repita os passos acima at que uma soluo seja obtida ou at que no haja mais escolhas a partir da posio corrente Representao da informao para refinar a soluo:
-

tabuleiro: matriz de inteiros T de dimensional n n, sendo que: T [x,y] = 0 indica que a posio (x,y) ainda no foi visitada T [x,y] = i indica que a posio (x,y) foi visitada no i-simo movimento;

- movimentos possveis: o movimento do cavalo consiste em andar duas casas numa direo e uma casa na outra direo, isto , a partir da posio (x,y) os 8 possveis movimentos so dados por (x+2, y+1) (x+1, y+2) (x -1, y+2) (x -2, y+1) (x -2, y -1) (x -1, y -2) (x+1, y -2) (x+2, y -1)

Portanto, os possveis movimentos podem ser obtidos representando-se os deslocamentos nas direes x e y por um vetor com 8 posies sendo que cada posio contm os deslocamentos dx e dy, isto k 1 2 3 4 dx 2 1 1 2 dy 1 2 2 1 k 5 6 7 8 dx 2 1 1 2 dy 1 2 2 1
5

Programa
/* +---------------------------------------------+ | Programa que determina o passeio do cavalo | | num tabuleiro de xadrez de dimenses n x n | | onde n fornecido pelo usurio | | Implementado por Marcus Vincius A. Andrade | | em 28/02/02 | +---------------------------------------------+ */ #include <iostream.h> #include <iomanip.h> int n; struct desloc { int dx; int dy; };

// deslocamentos nas direes x e y

// vetor de deslocamentos que define os possveis // movimentos do cavalo no tabuleiro de xadrez desloc mov_cav[8]={{ 2, 1},{ 1, 2},{-1, 2},{-2, 1}, {-2,-1},{-1,-2},{ 1,-2},{ 2,-1}}; int **T; int nsq; // // tabuleiro nmero de posioes no tabuleiro n^2

bool tente_mov(int i, int x, int y) { int u,v; // posio do prximo movimento bool q; // true => movimento com sucesso int k; k=0; do { q=false; u = x+mov_cav[k].dx; v = y+mov_cav[k].dy; k=k+1; // verifica se a posio vlida no tabuleiro // e se a posio ainda no foi visitada if (0 <= u && u < n && 0 <= v && v < n && T[u][v]==0) { T[u][v]=i; // registra a visita

if (i < nsq) { // ainda h posies no visitadas no tabuleiro q = tente_mov(i+1,u,v); if (!q) // movimento sem sucesso T[u][v]=0; // remova o registo de "visita" } else q=true; } } while (!q && k<8); return q; }

void main() { bool ok; cout << "Tamanho do tabuleiro = "; cin >> n; nsq = n*n; // Aloca espao para o tabuleiro T=new (int* [n]); for (int i=0; i < n; i++) T[i]=new (int[n]); for (int i=0; i < n; i++) for (int j=0; j < n; j++) T[i][j]=0; T[0][0]=1; ok=tente_mov(2,0,0); if (ok) { cout.setf(ios::right); for (int i=0; i < n; i++) { for (int j=0; j < n; j++) cout << setw(4) << T[i][j] << " cout << endl; } } else cout << "Nao ha solucao \n"; }

";