• Nenhum resultado encontrado

Tópicos Especiais em Ciência da Computação I

N/A
N/A
Protected

Academic year: 2021

Share "Tópicos Especiais em Ciência da Computação I"

Copied!
14
0
0

Texto

(1)

Tópicos Especiais em Ciência da

Computação I

Professora: Alessandra Martins Coelho 2° semestre/2012

Métodos Heurísticos Aplicados a

Problemas de Otimização

Introdução

Durante muitas décadas, a investigação em informática levou ao desenvolvimento de muitos algoritmos para resolver as classes de problemas de otimalidade. Basicamente, pode-se distinguir dois tipos de algoritmos para a resolução de problemas: algoritmos dedicados e algoritmos de otimização.

Algoritmos dedicados são específicos para resolver exatamente uma determinada classe de problemas, no menor tempo possível. Eles são, na maioria das vezes, determinísticos e sempre utilizam o conhecimento teórico exato sobre o problema a ser abordado. O Algoritmo de Kruskal, por exemplo, é a melhor maneira para pesquisar a árvore geradora mínima em um grafo com arestas ponderadas. Os caminhos mais curtos a partir de um nó fonte para os outros nós em uma rede, pode ser melhor encontrado com o algoritmo de Dijkstra e o fluxo máximo em uma rede de fluxo pode ser calculado rapidamente com o algoritmo de Dinitz. Há muitos problemas para os quais esses rápidos e eficientes algoritmos dedicados existem. Para cada problema de otimização, deve-se, primeiramente, verificar se ele pode ser resolvido por um determinado algoritmo exato.

No entanto, para muitas tarefas de otimização, não existe algoritmo eficiente, como, por exemplo, uma grande variedade de problemas do mundo real que pode ser modelada como problemas de otimização combinatória. Em geral, problemas complexos e de larga-escala são considerados difíceis de resolver e não podem ser resolvidos de maneira eficiente por técnicas determinísticas. A razão pode ser (1) devido ao problema ser muito específico. (2) Além disso, para alguns problemas (o parecer científico atual é que) se os algoritmos exatos não são eficientes, algoritmos dedicados podem ser construídos para tudo. Para tais problemas, os algoritmos de otimização mais gerais são empregados. Frequentemente, esses algoritmos só precisam de uma definição da estrutura de soluções possíveis e uma função f para medir a qualidade de uma solução candidata. Com base nessas informações, eles tentam encontrar soluções para as quais f assume os melhores valores. Métodos de otimização utilizam muito menos informações do que algoritmos exatos, eles são geralmente mais lentos e não se tem a certeza do fornecimento de soluções com a mesma qualidade. No caso de problemas específicos, no entanto, não se têm escolha. De fato, existe uma qrande quantidade de situações em que as condições (1), (2) ou ambas, são enquadradas. A dificuldade desses problemas pode ser caracterizada pela teoria da complexidade computacional. Duas das principais dificuldades nesses problemas são escapar de regiões sub-ótimas e evitar convergência prematura do algoritmo.

(2)

À medida que a complexidade do problema aumenta, devido a um grande número de variáveis ou de regiões sub-ótimas, o tempo computacional torna-se grande e a possibilidade de que o algoritmo encontre o ótimo global diminui consideravelmente. No entanto, em algumas situações, é suficiente obter uma solução satisfatória para o problema tratado, sem grandes garantias de qualidade. Um exemplo é quando a incerteza nos dados implica que o ótimo não tenha grande significado. Em outras situações, pretende-se encontrar uma ou, ainda melhor, várias soluções aceitáveis de boa qualidade.

Desse modo, algoritmos probabilísticos, como os métodos heurísticos, têm sido amplamente empregados. Com esses métodos, pretende-se encontrar soluções que possam ser colocadas em prática, ainda que não sejam ótimas, ou não se tenha provas de que o são. Esses métodos têm como finalidade, encontrar soluções de boa qualidade em um tempo razoável para os fins práticos a que se destinam.

Uma boa parte das heurísticas é desenvolvida para resolver especificamente uma classe de problemas. Na busca da solução de problemas de maior complexidade e de larga-escala, para os quais não há heurísticas adequadas ou mesmo algoritmos de busca local que sejam capazes de encontrar soluções satisfatórias, surgiram as metaheurísticas. As metaheurísticas são algoritmos simples e genéricos, que podem ser aplicados a uma vasta gama de problemas.

1 Algoritmos e Programas

O termo algoritmo é derivado do nome do matemático Abu Já'far Mohamed ibn Musa al-Khwarizmi que fazia parte da corte real em Bagdá, e que viveu aproximadamente nos anos de 780 a 850. Quando se fala em algoritmos, pensa-se, sobretudo, em computadores. No entanto, outros métodos sistemáticos para a solução de problemas poderiam ser incluídos, como, por exemplo, os métodos ensinados na escola para multiplicar e dividir números inteiros. É ainda possível considerar certas receitas culinárias como algoritmos, desde que não incluam instruções como "Adicione sal a gosto".

O algoritmo mais famoso da história remonta ao tempo dos gregos. O algoritmo de Euclides é usado para o cálculo do máximo divisor comum de dois números inteiros.

Do dicionário Aurélio tem-se que algoritmo é o processo de cálculo ou de resolução de um grupo de problemas semelhantes, em que se estipulam, com generalidade e sem restrições, regras formais para a obtenção do resultado, ou da solução do problema.

Outros conceitos:

- é qualquer procedimento computacional bem definido que toma algum valor ou conjunto de valores como entrada e produz algum valor ou conjunto de valores como saída. Portanto, um algoritmo é uma sequência de passos computacionais que transforma entrada em saída;

- Um algoritmo é um conjunto de instruções em uma representação que é geralmente compreensível para os seres humanos e, portanto, independentes de hardware específico e computadores. Um programa, por outro lado, é basicamente um algoritmo realizado para um determinado computador ou ambiente de execução.

Algoritmos diferentes podem ser usados para resolver o mesmo problema e programas diferentes podem ser usados para descrever o mesmo algoritmo. Neste sentido, um programa é um conjunto de instruções que descrevem uma tarefa ou um algoritmo para ser realizado em um computador. Portanto, as instruções do algoritmo devem ser expressas, quer de um modo que a máquina possa processar diretamente (código de máquina), de uma maneira que possa ser traduzido em tal código (1:1) (ex.

(3)

linguagem assembly), ou em uma programação de alto nível, que possa ser traduzida para o último, usando software especial (n: m) (compilador).

Quando alguém se propõe a resolver um problema, o primeiro passo é decidir qual algoritmo deverá ser usado para sua solução. Essa decisão pode depender de muitos fatores, quais sejam: o tamanho da instância a ser resolvido, a maneira que o problema é apresentado, a velocidade e o tamanho da memória do computador disponível, e assim por diante.

Exemplo 1: Multiplicação de dois números inteiros É assim que costumamos multiplicar:

Mas nem sempre as multiplicações foram realizadas dessa maneira. Outro exemplo: Multiplicação de La Russe.

Existem algoritmos mais eficientes quando os inteiros a serem multiplicados são muito grandes. No entanto, esses algoritmos mais sofisticados são, de fato, mais lentos, do que os mais simples, quando os operandos não são suficientemente grandes. Diante do exposto, é importante decidir como será representado o algoritmo.

1. 1 O que os algoritmos podem resolver?

Tudo isto leva-nos a uma noção central oculta ao mundo dos algorítmos e computação - o problema algorítmico, que é o que um algoritmo é projetado para resolver, ou seja, é um problema para o qual existe uma solução na forma de um algoritmo.

Figura 1: O problema algorítmico e sua solução

qualquer entrada legal Especificação de todas as entradas legais Caracterização do produto desejado como uma função

da entrada

e algoritmo O

A saída desejada

O problema algoritmico Um algoritmo que resolve o problema

(4)

A descrição de um problema algorítmico deve incluir dois itens, quais sejam: (1) uma definição precisa do conjunto de entradas válidas; (2) uma caracterização precisa da saída desejada em função dos dados de entrada. Uma representação do problema algoritmico e sua solução é apresentado na figura 1.

Seguem alguns exemplos de problemas algorítmicos. Cada um é definido, como é apropriado, por um conjunto de entradas legais e uma descrição da saída desejada.

Problema 1:

entrada: 2 números inteiros i e j saída: produto i ² + 3j

Um problema simples, que exige um cálculo aritmético em dois números de entrada Problema 2:

entrada: um número inteiro e positivo k saída: soma dos números inteiros de 1 a k

Este problema também envolve aritmética, mas o número de elementos que se trata varia e depende da própria entrada.

Problema 3

entrada: um número positivo inteiro k saída: SIM, se k é primo e NÃO se não for

Este pode ser referido como um problema de decisão. Ele é chamado para decidir o status do seu número de entrada. (Recorde-se que um número primo é um número inteiro positivo maior que 1, que pode ser dividido por um e por ele mesmo. Por exemplo, 2, 17, e 113 são números primos, enquanto que 6, 91 e 133 não o são, são chamados de compostos).

Resolver este problema certamente irá envolver aritmética, mas não fornece um resultado numérico, apenas um SIM ou um NÃO.

Problema 4

entrada: uma lista L de palavras em Inglês

saída: a lista L classificados em ordem alfabética (lexicográfica).

Este é um problema não-aritmético, mas, como o problema 2, tem que lidar com um número variável de elementos e, neste caso, palavras.

Muitos problemas de algoritmos que aparecem no mundo real, todos os dias, não são fáceis de definir. Às vezes, a dificuldade está em especificar a saída necessária, como ao pedir a melhor jogada para uma posição legal do tabuleiro de xadrez (o que exatamente é o melhor?).

Em casos de ordem, descrever as entradas pode ser complicado. Suponho a existência de 20000 jornais a serem distribuídos para 1000 pontos de entrega em 100 cidades, utilizando 50 caminhões. A entrada contém as distâncias rodoviárias entre os pontos de entrega em cada cidade, o número de jornais necessários em cada ponto, a posição atual de cada caminhão, detalhes de estradas disponíveis, incluindo o seu atual paradeiro, e a capacidade de jornais carregada em cada caminhão, capacidade de gasolina e desempenho por galão. Espera-se como saída uma lista, contendo as unidades correspondentes e destinos dos caminhões de uma forma que minimize o custo

(5)

total para a empresa de distribuição. Na verdade, o problema exige um algoritmo que funciona para qualquer número de jornais, cidades, pontos de entrega, e caminhões. Alguns problemas são difíceis de se definir as entradas, bem como são difíceis de se especificar as realizações, tais como as necessárias para prever o tempo ou para avaliar estoque, tais como os necessários para prever o tempo para avaliar investimentos de uma bolsa de valores, dentre outros.

1.2 Problemas e Instâncias

Quando um problema algorítmico é aplicado a uma entrada especial, isso é chamado de uma instância do problema.

Um problema algoritmo, em geral, possui muitas instâncias, e um algoritmo é dito correto quando ele sempre termina e produz uma resposta correta para todas as instâncias de um dado problema.

A maioria dos problemas interessantes incluem uma coleção infinita de casos. Um algoritmo deve funcionar corretamente em cada instância do problema que pretende resolver. Para mostrar que um algoritmo é incorreto, é preciso apenas encontrar uma instância do problema para o qual ele seja incapaz de encontrar uma resposta correta. Por outro lado, é geralmente mais difícil provar que um algoritmo é correto.

Ao especificar um problema, é importante definir o seu domínio, isto é, o conjunto de instâncias a serem consideradas. Por exemplo, a multiplicalçao de La Russe não funciona quando o primeiro operando é negativo, no entanto, isso não invalida o algoritmo uma vez que, por exemplo, (-45,19) não é uma instância do problema a ser considerado. 1.3 Resolução de problemas algorítmicos

Um problema algorítmico é resolvido quando um algoritmo apropriado foi encontrado.

E o que é apropriado? Bem, o algoritmo deve fornecer saídas corretas para todas as entradas. Um algoritmo de solução que funciona bem somente para algumas das entradas não é bom o suficiente.

Encontrar soluções para muitos dos problemas de amostragem descritos anteriormente (problemas de 1 a 4) é fácil. Computar i² + 3j é trivial (assumindo, evidentemente, já possuir operações básicas para adição e multiplicação), e do mesmo modo, a soma dos números inteiros de 1 a k. Neste último caso, é claro, é necessário o uso de um contador para manter o controle de quanto já foi e para parar o processo quando chegar a k.

Para testar se um número k é primo, basta dividi-lo por todos os inteiros de 2 a k -1, parar e dizer não, caso seja encontrado algum inteiro que divide k sem resto, e parar e dizer sim apenas quando todas as divisões foram concluídas e todos os números produziram restos (claro que este algoritmo pode ser melhorado).

Alguns dos outros problemas também podem ser resolvidos de maneira mais eficiente do que as mencionadas acima. Contudo, eficiência e praticidade de algoritmos não serão abordados nesta introdução, uma vez que a intenção foi a exigência do mínimo para que um algoritmo pudesse, de fato, resolver um problema, proporcionando saídas corretas para todas entradas legais, embora pudesse fazê-lo de ineficientemente.

1.4 Existem Problemas que não podem ser resolvidos por computador?

Sim, existem problemas interessantes e importantes para a qual simplesmente não há algoritmos, e não importa o quanto somos inteligentes, ou quão sofisticado e poderoso

(6)

é o nosso computador, nosso software, linguagens de programação, e nossos métodos algorítmicos, eles nunca serão resolvidos.

Um dia, seu chefe o chamou em sua sala e lhe informou que a empresa está prestes a entrar no mercado altamente competitivo de "Bandersnatch". Um bom método é necessário para determinar a existência ou não de qualquer conjunto de dados de especificações para um novo componente Bandersnatch poder ser atendido e, em caso afirmativo, para a construção de um projeto que os atenda. Você é o responsável da empresa pela construção de algoritmos, o seu trabalho é encontrar um algoritmo eficiente para fazer isso.

Algumas semanas depois, você não foi capaz de chegar a qualquer algoritmo substancialmente melhor do que procurar por todos projetos possíveis.

Isso implicaria anos de tempo de computação para apenas um conjunto de especificações.

Você simplesmente volta para o escritório de seu chefe e relata: "Eu não consegui encontrar um algoritmo eficiente, eu acho que eu sou muito burro. "

(7)

Mas talvez isso seja injusto com você: o problema pode ser demasiadamente difícil. Por isso, seria muito melhor se você pudesse provar que o problema Bandersnatch é intratável, que não existe algoritmo que o resolva rapidamente. Então você poderia entrar com confiança no escritório do seu chefe e dizer: "Eu não consigo encontrar um algoritmo eficiente, porque tal algoritmo não é possível. "

Para tais "zonas cinzentas" de um problema, um modo alternativo é provar que o problema é "tão difícil quanto" um grande número de outros problemas que são amplamente reconhecidos como sendo difícil e que vêm perturbando os especialistas há anos.

“Eu não consigo encontrar um algoritmo eficiente, e nenhuma dessas pessoas famosas conseguem!”

(8)

Consequências:

No mínimo, isso mostraria a seu chefe que demiti-lo e contratar outra pessoa para

escrever algoritmos não seria a melhor opção.

Mais importante: você poderia gastar seu tempo procurando algoritmos eficientes que resolvem vários casos especiais do problema geral.

Por este ponto de vista, os problemas podem ser classificados como:

1.4.1 Exemplos de problemas não computáveis Problema de ladrilhos (Tiling)

O problema envolve cobrir grandes áreas utilizando ladrilhos com bordas coloridas, sendo que um ladrilho é um quadrado de 1 por 1, dividido em quatro pelas duas diagonais, cada quarto colorido com alguma cor. Os ladrilhos têm orientação fixa e não podem ser girados.

Entrada: um conjunto finito T de descrições de azulejos.

Problema: é possível azulejar qualquer área de uma grade regular quadrada finita, de qualquer tamanho, usando somente os azulejos descritos em T, casando as cores das faces que se tocam? SIM ou NÃO?

OBS: pode usar quantos ladrilhos quiser de cada tipo

os azulejos possuem orientação fixa, ou seja, não podem ser girados Problemas

Tratáveis

admite algoritmos razoáveis (em tempo

polinomial)

tão difíceis que nenhum algoritmo polinomial consiga resolvê-lo

Problemas Intratáveis Indecidíveis (não-computáveis) não admitem algoritmos

(9)

Ao projetar o algoritmo, não se sabe quais os tipos de ladrilhos existentes, nem as dimensões da grade. Estas são as entradas. O algoritmo tem que ser geral o suficiente para lidar com todas as entradas legais. O que se espera do algoritmo é que ele responda SIM ou NÃO.

Exemplo 1: O problema de azulejar toda a região do plano Entrada:

Área:

Resultado:

O exemplo 1, cima, mostra três tipos de ladrilhos e uma malha 3x3. Você não deve ter dificuldade em verificar que o padrão, na parte inferior da figura pode ser estendido indefinidamente em todas as direções, para se obter uma grade de qualquer domínio. Em contraste, se pudermos as cores de fundo de azulejos (2) e (3) pode ser demonstrado facilmente que mesmo grades muito pequenas não podem se preenchidas completamente. Exemplo 2 pretende ser uma ilustração deste fato.

Exemplo 2: Entrada:

(10)

Resultado:

Um algoritmo para o problema de ladrilhos deve responder "SIM" para o exemplo 1 “NÃO” para o exemplo 2.

PROBLEMA: é possível azulejar qualquer área de uma grade regular quadrada finita, de qualquer tamanho, usando somente os azulejos descritos em T, casando as cores das faces que se tocam?

• Esse raciocínio é impossível mecanizar. Não há nenhum algoritmo, e nunca haverá, para resolver-lo

• Para qualquer algoritmos que se possa projetar para o problema, sempre haverá T conjuntos de entrada para os quais o algoritmo possa executar e nunca terminar ou, poderá haver casos em que ele termine, mas com uma resposta incorreta. PROBLEMA EQUIVALENTE: (1) suponha que temos como entrada um azulejo na forma de um polígono qualquer, sem restrição de casamento de padrão e que temos que azulejar todo o plano. Temos infinitos azulejos disponíveis.

Problema indecidível? Qual seria a razão?

PROBLEMA EQUIVALENTE: (2) fixando a forma (polígonos regulares – lados e ângulos tem a mesma medida), todos do mesmo tipo e cada vértice deve ser igual.

(11)

Para certas instâncias...

O problema do azulejamento é decidível para certas instâncias. O que foi provado ser indecidível é o problema que pergunta se o azulejamento é possível para todos os polígonos.

Existem conjuntos de azulejos que azulejam o plano, porém, não o fazem periodicamente (repetidamente)!

Caso contrário...

Este problema seria resolvido por um algoritmo que checaria todas as áreas finitas exaustivamente, procurando por uma área finita que não pode ser azulejada ou uma que admita um azulejamento em todas as direções.

O problema da parada

O Problema da Parada (The Halting Problem) é um problema de decisão clássico da Ciência da Computação que consiste, basicamente, em determinar se um dado programa sempre vai parar para uma dada entrada arbitrária (ou seja, terminar sua execução) ou se vai executar infinitamente.

Se o número de dados é finito, o problema consiste em verificar para todos os dados, caso contrário, é impossível provar que ele pára para qualquer dado do conjunto de dados possíveis.

Considere o seguinte algoritmo A: (1) enquanto X <> 1 faça X ← X − 2; (2) parar

Sim!!!

Sim!!!

Não!!!

Sim!!!

Não!!!

(12)

O algoritmo A deve reduzir 2 do valor X até que o valor seja igual a 1. Na hipótese das entradas serem números inteiros positívos, o algoritmo pára para as entradas ímpares. Assim, para este algoritmo, em particular, decidir se uma entrada legal fará com que ele termine é trivial: basta verificar se a entrada é par ou ímpar e responder “SIM” para ímpar e “NÃO” para par.

Considere o algoritmo B: (1) enquanto X <> 1 faça

(1.1) se X é par faça X ← X/2;

(1.2) senão (se X é ímpar) faça X ← 3X + 1; (2) parar.

O algoritmo B divide X por 2 se ele for par, mas acrescenta três vezes X mais 1, se ele é ímpar Por exemplo, se a entrada de B for 7, a seqüência de valores é: 7, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1.

Se tentarmos executar o algoritmo com algum inteiro positivo arbitrário veremos que ele termina. A seqüência de valores muitas vezes é bastante incomum, chegando a valores muito altos antes de atingir 1. Na verdade, ao longo dos anos B foi testado com várias entradas que sempre terminaram. No entanto, ninguém foi capaz de provar que ele termina para todos os inteiros positivos, embora a maioria das pessoas acreditam nisso. Estes exemplos ilustram o quão difícil é analisar as propriedades de parada de algoritmos, mesmo sendo muito simples.

A classificação pormenorizada dos problemas indecidíveis para os vários níveis de indecidibilidade ainda é uma direção de pesquisa ativa. Muito trabalho é dedicado a refinar e compreender as várias hierarquias de indecidibilidade e suas inter-relações. Além disso, os cientistas estão interessados em encontrar problemas simples que possam servir de base para as reduções que exibem a indecidibilidade de outros problemas. Para muitos problemas de interesse, tais como o problema de satisfatibilidade, ou o problema de equivalência sintática das línguas, a linha que separa as versões de decidíveis dos indecidíveis não é suficientemente clara, e uma profunda compreensão das questões relevantes é necessária.

Problemas que não são solucionáveis por qualquer tipo de algoritmos executáveis de maneira eficaz realmente são a parte pessimista da história, e é hora de voltar aos mais felizes, as questões mais brilhantes. Deve ser lembrado, contudo, que quando se tenta resolver um problema algorítmico há sempre a chance de que ele possa não ter solução em todas as entradas, ou não possa admitir qualquer solução prática aceitável. 1.5 A eficiência dos algoritmos

Quando se tem um problema para resolver, torna-se evidente o interesse de encontrar vários algoritmos que possam ser usados para que possamos escolher o melhor.

E porque buscar por algoritmos eficientes?

Como os computadores ficam cada vez mais rápidos, pode parecer que pouco vale a pena gastar o tempo tentando projetar algoritmos mais eficientes. Não seria mais fácil simplesmente esperar a próxima geração de computadores? No entanto, existem muitos motivos que podem mostrar que isto não é verdade.

Suponha, para ilustrar o argumento, que, para resolver um problema particular que tem-se disponível um algoritmo exponencial e um computador capaz de executar esse

(13)

algoritmo em instâncias de tamanho n, em 10-4 x 2n segundos. O programa pode, assim, resolver uma instância de tamanho 10 em um décimo de segundo. Uma instância de tamanho 20, em quase dois minutos. Já a de tamanho 30, um dia inteiro não seria suficiente. E, supondo que o computador fosse deixado em execução, sem interrupção durante um ano, o maior tamanho da instância seria 38.

E se fosse necessário resolver instâncias maiores do que isso? Poderia ser realizada a compra de um novo computador centenas de vezes mais rápido do que o primeiro. Com o mesmo algoritmo, agora, seria possível resolver uma instância de tamanho n em apenas 10-6 x 2n segundos. Com essa nova máquina, caso o mesmo

algoritmo fosse executado por um ano inteiro, o tamaho da instancia passaria para 45. E, se em vez disso, fosse investido em um novo algoritmo para ser testado na primeira máquina de modo que ele pudesse resover uma instância de tamanho n em 10-2

x n3 segundos? Em um dia seria possível resolver instâncias de tamanho maior que 200. E com a execução de um ano n estaria próximo a 1500.

Em se tratando de instâncias, um algoritmo não deve ser utilizado, sem crítica, em todas as instâncias do problema. Suponha que o primeiro algoritmo utilizado resolvesse melhor as instâncias pequenas e o segundo algoritmo as instâncias maiores que 20. Seria viável combinar os dois algoritmos em um terceiro para verificar o tamanho da instância a ser resolvida antes de decidir qual método a ser usado.

Diante do exposto acima, pode-se concluir que qualquer equipamento de computação real tem um limite para o tamanho dos casos que ele possa manipular. Além disso, algoritmos criados para resolver o mesmo problema, muitas vezes podem diferir drasticamente em sua eficiência. Essas diferenças podem ser muito mais significativas que as diferenças relativas a hardware e software.

As medidas de complexidade são usadas como medida de eficiência de um algoritmo. Assim, um algoritmo é dito eficiente quando a sua complexidade for polinomial em relação ao tamanho de sua entrada, ou seja, O(nk) para alguma constante k>0.

Exemplo1: Seja m e n dois números inteiros positivos. O maior divisor comum de m e n, denotado por mdc (m, n), é o maior número inteiro que divide exatamente ambos. Quando mdc (m, n) = 1, dizemos que m e n são primos entre si.

Exemplo2: A sequência de Fibonacci é definida pela seguinte recorrência: Fo=0;

F1=1;

Fn= Fn-1 -Fn-2, para n>2

Os primeiros 10 termos da sequência são os seguintes: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34

A sequência de Fibonacci tem inúmeras aplicações em ciência da computação, na matemática e na teoria de jogos.

Exercícios:

1) Faça três algoritmos para calcular o mdc, sendo um deles recursivo. Implemente em uma linguagem e realize testes para verificar o desempenho. Informe as configurações do equipamento que está utilizando, verifique o tempo de processamento e, por fim, informe qual algoritmo foi mais eficiente.

(14)

2) Faça três algoritmos para informar um determinado termo da sequência de fibonacci. Implemente em uma linguagem e realize testes para verificar o desempenho. Informe as configurações do equipamento que está utilizando, verifique o tempo de processamento e, por fim, informe qual algoritmo foi mais eficiente.

3) São dados N azulejos de dimensões 15cm x 15cm. Com eles, deve-se montar um conjunto de quadrados (com espessura de um azulejo) de modo a utilizar TODOS os azulejos dados. Inicialmente deve-se montar o maior quadrado possível com os azulejos dados; então, com os azulejos que sobraram, você deve montar o maior quadrado possível, e assim sucessivamente. Por exemplo, se forem dados 31 azulejos, o conjunto montado terá quatro quadrados.

Exemplo:

Quantos quadrados são montados com 31 azulejos?

Resposta: conjunto com quatro quadrados montado a partir de 31 azulejos

Referências:

CORMEN, Thomas H. et al. Introduction to algorithms. 3. ed. Cambridge, Massachusetts: MIT Press, c2009. 1292 p. AHO, Alfred V.; HOPCROFT, John E.; ULLMAN, Jeffrey D.. The design and analysis of computer algorithms. USA: Addison-Wesley, c1974. 470 p HAREL, David; FELDMAN, Yishai. Algorithmics : the spirit of computing. Addison Wesley,

2004.

BRASSARD, Gilles. Algorithmics: theory and practice. Prentice-Hall, 1988

GAREY, M. R., JOHNSON, D.S. Computers and Intractability – A Guide to the Theory of NP-Completeness. New York: W.H. Freeman. 1979

Referências

Documentos relacionados

De acordo com Erber e Sayed-Ahmed (2005, p.100), considerando-se o país de origem, esta forma específica de outsourcing pode ser definida como a “realocação dos processos de

Autor: Hericlis Martins Soares Orientador: Glauber Costa..

Em função da forma de comunicação entre os processadores e o grau de Em função da forma de comunicação entre os processadores e o grau de compartilhamento da memória principal e

Há componentes curriculares para a formação fundamental em Computação, que estudam conceitos e fundamentação em Ciência da Computação, imprescindíveis ao

A média de tempo de espera mostra que no cenário de um escalonador FIFO, onde não existe preempção, ou prioridades, os processos precisam esperar em ordem de chegada na fila

Ementa: Fundamentos teóricos e práticos da interação ser humano-computador. Paradigmas de interação. Modelagem, projeto e concretização de interfaces. Modelos e frameworks

O projetista determina que é possível haver um aumento substancial na taxa de clock, mas esse aumento afetará o restante do projeto que da CPU, fazendo com que o

Ciência da Computação Doutorado Corina Maria Tedeschi Busnardo Efetivo 40h Letras Anglo-Portuguesas Doutorado Daniel dos Santos Kaster Efetivo Tide Bel. Ciência da Computação