Programação de Computadores II TCC-00.174 Profs.: Leandro A. F. Fernandes (Turma A1) & Marcos Lage (Turma B1) (Turma A1) www.ic.uff.br/~laffernandes (Turma B1) www.ic.uff.br/~mlage Conteúdo: Material elaborado pelos profs. Anselmo Montenegro e Marcos Lage com contribuições do prof. Leandro A. F. Fernandes Introdução Busca sistemática de todas as soluções possíveis Garante que a solução será encontrada, por enumerar todas as possibilidades Garante eficiencia, nunca testando uma solução mais de uma vez 30/01/2013 Programação de Computadores II 2 1
Introdução Utiliza força bruta, ao fazer busca exaustiva Prunning: otimização que consistem em descartar resultados parciais que não conduzem ao resultado desejado 30/01/2013 Programação de Computadores II 3 Ideia Central Método baseado em tentativa e erro Váriasseqüênciasde decisõessãotestadas, até quea solução seja encontrada Usada quando se quer achar soluções para problemas paraosque não se conhece uma regra fixade computação 30/01/2013 Programação de Computadores II 4 2
Abordagem Passo1: Decomporo processoemum númerofinitode subtarefas parciais(expressas de forma recursiva) Passo 2: Explora-las exaustivamente sem repetir computação Sempre que possível: Descartar caminhos não promissores 30/01/2013 Programação de Computadores II 5 Rotina genérica Solução é modelada como um vetor (A 1, A 2,..., A N ) Cada elemento A i representa uma parte da solução Ex.: Uma jogada de uma sequência, um subconjunto de elementos, etc. A cada passo tem-se um solução parcial com K elementos (A 1, A 2,..., A K ) No passo atual, testa-se se a solução desejada foi encontrada, retorna sucesso em caso positivo Se não, tenta-se extender a solução adicionando mais um elemento no vetor (A 1, A 2,..., A K, A K+1 ) e continua-se o processo exploratório Se não há possibilidade de extensão, retorna falha 30/01/2013 Programação de Computadores II 6 3
Rotina genérica boolean finished = false; /* Todas soluções encontradas? */ void backtrack(int[] a, int k, SomeData input) { if (issolution(a, k, input)) processsolution(a, k, input); else { k = k + 1; int[] c = constructcandidates(a, k, input); for (int i = 0; i < c.length; i++) { a[k] = c[i]; backtrack(a, k, input); if (finished) return; 30/01/2013 Programação de Computadores II 7 Rotina genérica (continuação) issolution(a, k, input) Testa se os primeiros k elementos do arraya formam uma solução desejada (input permite passar dados específicos para a rotina) processsolution(a, k, input) Esta rotina imprime, conta, ou realiza o processamento desejado uma vez que a solução foi encontrada constructcandidates(a, k, input) Cria o arrayc com o conjunto completo de todos os possíveis candidatos para a posição k do arraya, dado o conteúdo das k-1 primeiras posições 30/01/2013 Programação de Computadores II 8 4
Construir todos os subconjuntos a partir de N elementos boolean issolution(final boolean[] a, int k) { return ((k + 1) == a.length); void processsolution(final boolean[] a, int k) { System.out.print("{"); for (int i = 0; i <= k; i++) if (a[i]) System.out.print(" " + i); System.out.println(" "); boolean[] constructcandidates(final boolean[] a, int k) { boolean[] c = new boolean[2]; c[0] = false; c[1] = true; return c; 30/01/2013 Programação de Computadores II 9 boolean issolution(final int[] a, int k) { return ((k + 1) == a.length); Construir todas as permutações de N elementos void processsolution(final int[] a, int k) { System.out.print("{"); for (int i = 0; i <= k; i++) System.out.print(" " + a[i]); System.out.println(" "); int[] constructcandidates(final int[] a, int k) { boolean[] inperm = new boolean[a.length]; for (int i = 0; i < k; i++) inperm[a[i]] = true; int n = 0; for (int i = 0; i < inperm.length; i++) if (!inperm[i]) n++; int[] c = new int[n]; for (int i = 0, j = 0; i < inperm.length; i++) if (!inperm[i]) c[j++] = i; return c; 30/01/2013 Programação de Computadores II 10 5
Sudoku 30/01/2013 Programação de Computadores II 11 8 rainhas 30/01/2013 Programação de Computadores II 12 6
Passeio do Cavalo 30/01/2013 Programação de Computadores II 13 Labirinto 30/01/2013 Programação de Computadores II 14 7
Problema da Partição Seja S o conjunto de números inteiros sem repetição. Deseja-se saber se S contém um subconjunto S tal que soma dos seus elementos seja exatamente igual a metade da soma dos elementos de S. Ou seja, trata-se de saber se o problema da partição para S tem uma solução e, em caso afirmativo, apresentar um subconjunto S que responde ao problema. Você deve resolver este problema usando um algoritmo de backtracking onde: i. as soluções são representadas por tuplas de tamanho variável ii. o valor do k-ésimo elemento da tupla é sempre menor do que o valor dos (k 1) elementos que o antecedem na tupla 30/01/2013 Programação de Computadores II 15 Eight 8 3 2 1 5 7 6 4 30/01/2013 Programação de Computadores II 16 8