Problema das n rainhas

Documentos relacionados
Problema das n rainhas AULA 24. Soluções. Problema das 8 rainhas. Problema das 8 rainhas

Problema das n rainhas AULA 19. Soluções. Problema das 8 rainhas. Problema das 8 rainhas

INF01056 Aula 07/08 Backtracking. Baseado no livro Programming Challenges

Algoritmos Tentativa e Erro (Backtracking) Prof.: Jonas Potros

Algoritmos de Enumeração

Introdução à Programação

Programação de Computadores II TCC

LISTAS ENCADEADAS OU NÃO- SEQÜENCIAIS. Estrutura de Dados

Tentativa e Erro (Backtracking)

Recursividade Exaustiva e Backtracking

SCC0601 Projeto de Algoritmos. Recursão

AULA 19 AULA 20. Ordenação: algoritmo Quicksort. Resumo. Melhores momentos

Listas Estáticas. Prof. Fernando V. Paulovich *Baseado no material do Prof. Gustavo Batista

Arvores binárias. Fonte: PF 14 pf/algoritmos/aulas/bint.html

Análise e Complexidade de Algoritmos

Questão 1: O histograma deve ser: [0, 1, 4, 2, 0, 3, 0,, 0, 2] Exemplo: Para a matriz

AULA 6. Conceitos. Melhores momentos. Conceitos. Conceitos. Conceitos. Conceitos

ÁRVORES ABB (ÁRVORES BINÁRIAS DE BUSCAS) Sérgio Carlos Portari Júnior

i a[i]

Estruturas de Dados Aula 11: TAD Pilha

Carlos Eduardo Batista. Centro de Informática - UFPB

Algoritmos e Estruturas de Dados I

Melhores momentos AULA 1

UNIVERSIDADE DA BEIRA INTERIOR

Listas Estáticas. SCC Algoritmos e Estruturas de Dados I. Prof. Fernando V. Paulovich. *Baseado no material do Prof.

Filas. Prof. Túlio Toffolo BCC202 Aula 12 Algoritmos e Estruturas de Dados I

Estruturas de Dados. Parte dos slides a seguir são adaptações, extensões e recodificações em C dos originais:

ALGORITMOS em linguagem C

SCC122 - Estruturas de Dados. Lista Estática Seqüencial

Aula 18: Vetores Introdução a Programação Túlio Toffolo & Puca Huachi

SCC Introdução à Ciência de Computação II. Recursão

Introdução à Programação

Programação Estruturada

1 se n = 0 n (n 1)! se n 1

Problemas e Estratégias. March 31, 2016

Capítulo VII : A Recorrência

Exemplos. Jogo dos oito :-) Mundo dos blocos (ex: torre de Hanoi) Poblema das rainhas. Criptoaritmética. Missionários e Canibais.

AULA 12 ESTRUTURA DE DADOS

Estruturas de Dados. Cristina Gomes Fernandes. Estruturas de Dados p. 1

Alocação Dinâmica. Túlio Toffolo BCC202 Aula 02 Algoritmos e Estruturas de Dados I

1 Exercícios com ponteiros

Bruno Hott Algoritmos e Estruturas de Dados I DECSI UFOP. Aula 07: Filas

LINGUAGEM C++ Prof. Bruno Gomes ESTRUTURAS DE DADOS HOMOGÊNEAS PARTE II - MATRIZES. Currais Novos, 2011

max1: 20,max2:+ max1:15, max2:20 max1:30,max2:32,max3:35 max1:40,max2:+

Introdução a Programação. Listas Encadeadas

Permite modularidade (dividir programa em partes): Facilita a depuração (debug) e portabilidade.

Listas Lineares. Livro Projeto de Algoritmos Nívio Ziviani Capítulo 3 Seção 3.1

Estruturas de dados e algoritmos fundamentais

Estruturas de Dados, Análise de Algoritmos e Complexidade Estrutural. Carlos Alberto Alonso Sanches

Introdução a Programação. Ponteiros e Strings, Alocação Dinâmica

UNIP - Ciência da Computação e Sistemas de Informação. Estrutura de Dados. AULA 5 Pilhas

Algoritmos e Programação de Computadores

SCC 202 Algoritmos e Estruturas de Dados I. Pilhas (Stacks) (implementação dinâmica)

Algoritmos e Estruturas de dados

Aula 16: Laços aninhados e desvios

Estruturas de Dados Aula 16: Árvores com Número Variável 13/06/2011

Lista Encadeada (Linked List)

MAC2166 Introdução à Computação

Melhores momentos AULA 2. Otimização Combinatória p. 71

Instituto de Física Segundo Semestre de Diurno. Prova Substitutiva 15/12/2000

UNIVERSIDADE DA BEIRA INTERIOR

/* definição de um novo tipo, o da tabela do jogo */ typedef int sudoku[max_lin][max_col]; sudoku_v1.c 1

Aula 05: Listas Encadeadas. Bruno Hott Algoritmos e Estruturas de Dados I DECSI UFOP

SCC0214 Projeto de Algoritmos

Algoritmo de Kruskal. Algoritmo de Kruskal. Floresta geradora 26. Subfloresta S 20.3

Pilhas e Filas. Algoritmos e Estruturas de Dados Flavio Figueiredo (

CES-11. Algoritmos e Estruturas de Dados. Carlos Alberto Alonso Sanches Juliana de Melo Bezerra

UNIVERSIDADE DA BEIRA INTERIOR

Fontes Bibliográficas. Estruturas de Dados Aula 15: Árvores. Livros:

Tipos Abstratos de Dados - Exercício

Laboratório 3 Comandos de repetição while, do-while e for

MAC 115 Introdução à Ciência da Computação ROTHELO

AULA 14 ESTRUTURA DE DADOS

INF1007: Programação 2 6 Ordenação de Vetores. 01/10/2015 (c) Dept. Informática - PUC-Rio 1

Programação: Vetores

INF 1010 Estruturas de Dados Avançadas

MATRIZES - PARTE Mais exemplos Multiplicação de duas matrizes AULA 26

Aula T19 BCC202 Pesquisa (Parte 1) Pesquisa Binária. Túlio Toffolo

SCC Capítulo 6 Paradigmas e Técnicas de Projetos de Algoritmos

double x; x = enigmab1(100);

Mais recursão ainda AULA 4. Máximo divisor comum. Divisibilidade. Máximo divisor comum. Divisibilidade PF 2.1, 2.2, 2.3 S 5.1

Aula T13 BCC202 Árvores. Túlio Toffolo

Árvore Binária Exemplo de Implementação

Estruturas de Dados. Módulo 17 - Busca. 2/6/2005 (c) Dept. Informática - PUC-Rio 1

MC102 Aula 27 Recursão II

Árvores Binárias de Busca

Resolução de Problemas. Resolução de Problemas. Primeiros problemas por computador: prova automática de teoremas e jogos.

Backtracking. Túlio Toffolo Marco Antônio Carvalho BCC402 Aula 10 Algoritmos e Programação Avançada

Computadores Digitais 2. Prof. Rodrigo de Souza Couto

Ponteiros, ponteiros e vetores e alocação dinâmica de memória

Lista de exercícios sobre contagem de operações Prof. João B. Oliveira

Listas ligadas/listas encadeadas

Aula 18 Algoritmos básicos de busca e classificação

1 Exercícios com ponteiros

14 Projeto de Algoritmos: paradigmas SCC201/501 - Introdução à Ciência de Computação II

UNIVERSIDADE DA BEIRA INTERIOR

INF 1007 Programação II

Transcrição:

AULA 24

Problema das n rainhas Fonte: http://www.bhmpics.com/ PF 12 http://www.ime.usp.br/ pf/algoritmos/aulas/enum.html http://en.wikipedia.org/wiki/eight_queens_puzzle

Problema das n rainhas Problema: Dado n determinar todas as maneiras de dispormos n rainhas em um tabuleiro "de xadrez" de dimensão n n de maneira que duas a duas elas não se atacam. Imagem: http://software.intel.com/en-us/articles/multicore-enabling-the-n-queens-problem-using-cilk/

Soluções Imagem: http://www.levelxgames.com/2012/05/n-queens/

Existem ( 64 8 ) Problema das 8 rainhas maneiras diferentes de dispormos 8 peças em um tabuleiro de dimensão 8 8 ( ) 64 = 4426165368 4,4 bilhões 8 Suponha que conseguimos vericar se uma conguração é válida em 10 3 segundos. Para vericarmos todas as 44 bilhões gastaríamos 4400000 seg 73333 min 1222 horas 51 dias.

Problema das 8 rainhas Como cada linha pode conter apenas uma rainha, podemos supor que a rainha i será colocada na coluna s[i] da linha i. Portanto as possíveis soluções para o problema são todas as sequências s[1], s[2],..., s[8] sobre 1, 2,..., 8 Existem 8 8 = 16777216 possibilidades. Para vericá-las gastaríamos 16777,216 seg 280 min 4,6 horas

Problema das 8 rainhas Existem outras restrições: (i) para cada i, j, k j, s[k] s[j] (=duas rainhas não ocupam a mesma coluna); e (ii) duas rainhas não podem ocupar uma mesma diagonal. Existem 8! = 40320 congurações que satisfazem (i). Essa congurações podem ser vericadas em 40 seg.

Função nrainhas A função nrainhas a seguir imprime todas as congurações de n rainhas em uma tabuleiro n n que duas a duas ela não se atacam. A função mantém no início da cada iteração a seguinte relação invariante (i0) s[1.. i 1] é uma solução parcial do problema Cada iteração procura estender essa solução colocando uma rainha na linha i

Função nrainhas A função utiliza as funções auxiliares /* Imprime tabuleiro com rainhas em s[1.. i] */ void mostretabuleiro(int n, int i, int *s); /* Supoe que s[1.. i-1] e solucao parcial, * verifica se s[1.. i] e solucao parcial */ int solucaoparcial(int i, int *s);

Função nrainhas void nrainhas (int n) { int i; /* linha atual */ int j; /* coluna candidata */ int njogadas = 0; /* num. da jogada */ int nsolucoes = 0; /* num. de sol. */ int *s = mallocsafe((n+1)*sizeof(int)); /* s[i] = coluna da linha i em que * esta a rainha i, para i= 1,...,n. * Posicao s[0] nao sera usada. */

Função nrainhas /* linha inicial e coluna inicial */ i = j = 1; /* Encontra todas as solucoes. */ while (i > 0) { /* s[1.. i-1] e' solucao parcial */ int achoupos = FALSE; while (j <= n && achoupos == FALSE) { s[i] = j; njogadas += 1; if (solucaoparcial(i,s) == TRUE) achoupos = TRUE; else j += 1; }

Função nrainhas } if (j <= n) {/* AVANCA */ i += 1; j = 1; if (i == n+1) { /* uma solucao foi encontrada */ nsolucoes++; mostretabuleiro(n,s); j = s[--i] + 1; /* volta */ } } else { /* BACKTRACKING */ j = s[--i]+1; }

Função nrainhas } printf(stdout,"\n no. jogadas = %d" "\n no. solucoes = %d.\n\n", njogadas, nsolucoes); free(s);

Rainhas em uma mesma diagonal Se duas rainhas estão nas posições [i][j] e [p][q] então elas estão em uma mesma diagonal se i + j == p + q ou i j == p q. Isto implica que duas rainhas estão em uma mesma diagonal se e somente se i p == q j ou i p == j q. ou seja i p == q j.

solucaoparcial A função solucaoparcial recebe um vetor s[1.. i] e supondo que s[1.. i-1] é uma solução parcial decide se s[1.. i] é uma solução parcial. Para isto a função apenas verica se a rainha colocada na posição [i][s[i]] está sendo ataca por alguma das rainhas colocadas nas posições [1][s[1]], [2][s[2]],..., [i 1][s[i 1]].

solucaoparcial int solucaoparcial(int i, int *s){ int j = s[i]; int k; for (k = 1; k < i; k++){ int p = k; int q = s[k]; if (q == j i+j == p+q i-j == p-q) return FALSE; } return TRUE; }

Alguns números nrainhas n jogadas soluções tempo 4 60 2 0.000s 8 15072 92 0.000s 10 348150 724 0.012s 12 10103868 14200 0.500s 14 377901398 365596 21.349s 15 2532748320 2279184 3m21s 16? 14772512 18m48s

Backtracking Backtracking (=tentativa e erro =busca exaustiva) é um método para encontrar uma ou todas as soluções de um problema. A obtenção de uma solução pode ser vista como uma sequência de passos/decisões. A cada momento temos uma solução parcial do problema. Assim, estamos em algum ponto de um caminho a procura de uma solução.

Backtracking Cada iteração consiste em tentar estender essa solução parcial, ou seja, dar mais um passo que nos aproxime de uma solução. Se não é possível estender a solução parcial, dar esse passo, voltamos no caminho e tomamos outra direção/decisão.

Backtracking Para descrever backtracking frequentemente é usada a metáfora "procura pela saída de um labirinto".

Backtracking A solução que vimos para o Problema das n rainhas é um exemplo clássico do emprego de backtracking. No início de cada iteração da função nrainhas temos que s[1.. i-1] é uma solução parcial: [1][s[1]],..., [i 1][s[i 1]] são posições de rainhas que duas a duas elas não se atacam.

Árvore de estados Imagem: http://cs.smith.edu/ thiebaut/transputer/chapter9/chap9-4.html

Árvore de estados Imagem: http://4c.ucc.ie/web/outreach/tutorial.html

Função nrainhas (outra versão) A função nrainhas a seguir imprime todas as congurações de n rainhas em uma tabuleiro n n que duas a duas ela não se atacam. A mantém no início da cada iteração a seguinte relação invariante (i0) s[1.. i 2] é uma solução parcial do problema Cada iteração procura estender essa solução colocando uma rainha na linha i

Função nrainhas (outra versão) A função utiliza as funções auxiliares /* Imprime tabuleiro com rainhas em s[1.. i] */ void mostretabuleiro(int n, int i, int *s); /* Supoe que s[1.. i-1] e solucao parcial, * verifica se s[1.. i] e solucao parcial */ int solucaoparcial(int i, int *s);

Função nrainhas (outra versão) void nrainhas (int n) { int testoutudo = FALSE; int i; /* linha atual */ int j; /* coluna candidata */ int njogadas = 0; /* num. da jogada */ int nsolucoes = 0; /* num. de sol. */ int *s = mallocsafe((n+1)*sizeof(int)); /* s[i] = coluna em que esta a rainha i * da linha i, para i= 1,...,n. * Posicao s[0] nao sera usada. */

Função nrainhas (outra versão) /* linha inicial e coluna inicial */ i = j = 1; /* Encontra todas as solucoes. */ while (testoutudo == FALSE) { /* s[1.. i-2] eh solucao parcial */ /* [i][j] e' onde pretendemos colocar uma rainha */ /* CASO 1: nlin == 0 */ if (i == 0) { testoutudo = TRUE; }

Função nrainhas (outra versão) /* CASO 2: j == n+1 OU s[1..i-1]) nao e' solucao parcial */ else if (j == n+1 solucaoparcial(i-1,s)==false){ /* BACKTRACKING */ /* voltamos para a linha anterior e * tentamos a proxima coluna */ j = s[--i]+1; /* stackpop() */ }

Função nrainhas (outra versão) /* Caso 3: i == n+1 */ else if (i == n+1) { /* uma solucao foi encontrada */ nsolucoes++; mostretabuleiro(n,i-1,s); /* retira do tabuleiro a ultima * rainha colocada e volta */ j = s[--i]+1; /* stackpop() */ }

Função nrainhas (outra versão) } /* CASO 4: j <= n && s[1..i-1] e solucao parcial */ else { /* AVANCA */ s[i++] = j; /* stackpush() */ j = 1; njogadas++; }

Função nrainhas (outra versão) } printf(stdout,"\n no. jogadas = %d" "\n no. solucoes = %d.\n\n", njogadas, nsolucoes); free(s);

Problema do passeio do cavalo Fonte: http://toonclips.com/design/5892 Creating a program to nd a knight's tour is a common problem given to computer science students PF 12 http://www.ime.usp.br/ pf/algoritmos/aulas/enum.html http://en.wikipedia.org/wiki/knight's_tour

Problema do passeio do cavalo Problema: Suponha dado um tabuleiro de xadrez n-por-n. Determinar se é possivel que um cavalo do jogo de xadrez parta da posição (1,1) e complete um passeio por todas as n 2 posições. Imagem: http://www.magic-squares.net/knighttours.htm/

Soluções +----+----+----+----+----+ 1 1 10 19 4 25 +----+----+----+----+----+ 2 18 5 2 9 14 +----+----+----+----+----+ 3 11 20 15 24 3 +----+----+----+----+----+ 4 6 17 22 13 8 +----+----+----+----+----+ 5 21 12 7 16 23 +----+----+----+----+----+ 1 2 3 4 5

Soluções +----+----+----+----+----+----+ 1 1 14 11 28 7 4 +----+----+----+----+----+----+ 2 12 27 2 5 10 29 +----+----+----+----+----+----+ 3 15 20 13 8 3 6 +----+----+----+----+----+----+ 4 26 33 24 19 30 9 +----+----+----+----+----+----+ 5 21 16 35 32 23 18 +----+----+----+----+----+----+ 6 34 25 22 17 36 31 +----+----+----+----+----+----+ 1 2 3 4 5 6

Soluções +----+----+----+----+----+----+----+ 1 1 18 27 6 11 16 13 +----+----+----+----+----+----+----+ 2 28 7 2 17 14 5 10 +----+----+----+----+----+----+----+ 3 19 26 29 8 3 12 15 +----+----+----+----+----+----+----+ 4 40 45 20 25 30 9 4 +----+----+----+----+----+----+----+ 5 37 34 39 44 21 24 31 +----+----+----+----+----+----+----+ 6 46 41 36 33 48 43 22 +----+----+----+----+----+----+----+ 7 35 38 47 42 23 32 49 +----+----+----+----+----+----+----+ 1 2 3 4 5 6 7

Movimentos do cavalo Imagem: http://www.mactech.com/articles/mactech/vol.14/14.11/theknightstour/index.html

Problema do passeio do cavalo Cada movimento possível é de um dos tipos 1,...,8 mostrados. De uma maneira grosseira existem 8 63 sequência de movimentos em um tabuleiro 8 8. 8 63 7.9 10 56 Supondo que conseguimos vericar cada sequência em 10 6 segundos, o tempo para vericar todas as sequências seria 7.9 10 50 seg 1.310 49 min 2.1 10 47 horas Deixa para lá...

Algoritmo passeiocavalo A função passeiocavalo a seguir imprime, caso exista, uma possível solução para o problema do passeio do cavalo em uma tabuleiro n n. A função mantém no início da cada iteração a seguinte relação invariante (i0) s[1.. k 1] são os movimentos de uma solução parcial do problema Cada iteração procura estender essa solução fazendo mais um movimento

Algoritmo passeiocavalo A função utiliza a função auxiliar e a struct /* Imprime o tabuleiro com as rainhas em s[1.. i] */ void mostretabuleiro(int n, int **tab); typedef struct { int i; int j; } Movimento;

Algoritmo passeiocavalo void passeiocavalo (int n) { int **tab; int i, j; /* posicao atual */ int iprox,jprox; /* coluna candidata */ int nmovimentos = 0; /* num. de mov */ int *s = malloc((n*n+1)*sizeof(int)); /* s[t] = movimento no passo t*/ int k; /* passo atual */

Algoritmo passeiocavalo Movimento movimento[nmov+1] = { {0,0}, /* fica parado */ {-1,+2}, /* movimento[1] */ {-2,+1}, /* movimento[2] */ {-2,-1}, {-1,-2}, {+1,-2}, {+2,-1}, {+2,+1}, {+1,+2} /* movimento[8] */ }; int mov;

Algoritmo passeiocavalo /* linha 0 e coluna 0 do tabuleiro nao serao usadas */ tab = malloc((n+1)*sizeof(int*)); for (i = 1; i <= n; i++) tab[i] = calloc(n+1,sizeof(int)); i = j = 1; /* posicao inicial */ k = 1; /* passo inicial */ mov = 1; /* movimento inicial */ tab[i][j] = 1; /* tabuleiro inicial */ iprox = jprox = 0; /* compilador feliz */

Algoritmo passeiocavalo while (0 < k && k < n*n) { int achoumov = FALSE; nmovimentos++; while(mov <= NMOV &&!achoumov){ iprox = i + movimento[mov].i; jprox = j + movimento[mov].j; if ( (0 < iprox && iprox <= n) && (0 < jprox && jprox <= n) && tab[iprox][jprox] == 0) achoumov = TRUE; else mov++; }

Algoritmo passeiocavalo if (mov <= NMOV) { /* AVANCA */ i = iprox; j = jprox; s[k] = mov; tab[i][j] = ++k; mov = 1; } else { /* BACKTRACKING */ tab[i][j] = 0; mov = s[--k]; i -= movimento[mov].i; j -= movimento[mov].j; mov++; }

Algoritmo passeiocavalo } if (k == n*n) { /* uma solucao foi encontrada */ mostretabuleiro(n,tab); } else printf("\n NAO TEM SOLUCAO\n"); /* libera memoria alocada */ free(s); for (i = 1; i <= n; i++) free(tab[i]); free(tab); printf("num. mov.=%d\n", nmovimentos);

Mais backtracking O esquema a seguir tenta descrever o método backtracking. Suponha que a solução de um problema pode ser vista como uma sequência de decisões x[1], x[2],..., x[n] Por exemplo, cada x[k] pode ser a posição de uma rainha ou para qual posição mover o cavalo. A relação invariante chave do método é algo como no início de cada iteração x[1.. k-1] é uma solução parcial (que pode ou não ser parte de uma solução)

Mais backtracking k 1 enquanto k > 1 faça procure valor para x[k] que ainda não foi testado e tal que x[1.. k] é solução parcial se encontrou candidato para x[k] então k k + 1 (avança) se k = n + 1 então encontramos uma solução devolva x[1.. n] k k 1 (continua) senão k k 1 (volta)

Enumeração de subsequências PF 12 http://www.ime.usp.br/ pf/algoritmos/aulas/enum.html

Enumeração de subsequências Problema: Enumerar todas as subsequências de 1,2,...,n, ou seja, fazer uma lista em que cada subsequência aparece uma e uma só vez. Exemplo: para n= 3 as subsequências são 1 1 2 1 2 3 1 3 2 2 3 3

Enumeração de subsequências Exemplo: para n= 4 as subsequências são 1 1 2 1 2 3 1 2 3 4 1 2 4 1 3 1 3 4 1 4 2 2 3 2 3 4 2 4 3 3 4 4

subseqlex A função subseqlex recebe n e imprime todas as subsequências não vazias de 1.. n. void subseqlex (int n) { int *s, k; s = mallocsafe((n+1) * sizeof(int)); s[0] = 0; k = 0;

subseqlex } while(1) { if (s[k] < n) { s[k+1] = s[k] + 1; k += 1; } else { s[k-1] += 1; k -= 1; } if (k == 0) break; imprima(s, k); } free(s);