Você está na página 1de 5

Análise de Soluções para o Problema dos Postos de

Combustível através de Programação Dinâmica e Algoritmos


Gulosos
Marcos Roberto Ribeiro, Stéfano Schwenck Borges Vale Vita

Programa de Pós-Graduação em Ciência da Computação – Universidade Federal de


Uberlândia (UFU)
Uberlândia – MG - Brasil
{mribeiro,stefano}@pos.facom.ufu.br

Abstract. This paper present solutions across dynamic programing and greedy
algorithms to the problem of gas station. Such problem is made up of get the
low number of stops for supply in a course, where are known the vehicle
autonomy and the distance between each gas station. The solve solutions are
analyzed and compared.

Resumo. Este artigo apresenta soluções através de programação dinâmica e


algoritmos gulosos para o problema dos postos de combustível. Tal problema
consiste em obter o menor número de paradas para abastecimento em um
trajeto, onde se conhece a autonomia do veículo e as distâncias entre cada
posto de combustível. As soluções obtidas são analisadas e comparadas.

1. Introdução
O problema dos postos de combustível consiste em obter o menor número de paradas
para abastecimento em um trajeto, onde se conhece a autonomia do veículo e as
distâncias entre os postos de combustível existentes no trajeto. A autonomia do veículo
refere-se a distância percorrida pelo mesmo após ser abastecido por completo. Deve ser
considerado que as distâncias entre os postos devem ser menores ou iguais a autonomia
do veículo, além disso, no ponto inicial o veículo encontra-se totalmente abastecido
[Cormen 2002].
O problema dos postos de combustível tem diversas aplicações reais, como em
programas que traçam rotas entre cidades e consideram as paradas para abastecimento.
Neste artigo são apresentadas possíveis soluções para o problema descrito, bem
como as análises de desempenho das mesmas. Os algoritmos presentes neste artigo
fazem uso de um pseudo-código semelhante a linguagem Pascal.
A seção 2 apresenta uma solução com o uso de programação dinâmica sendo
constituída de três subseções. A primeira subseção mostra a subestrutura ótima para o
problema, a segunda obtém a expressão de cálculo e a terceira exibe o algoritmo e a
análise do mesmo.
A seção 3 descreve uma solução através do uso de algoritmos gulosos. Esta
seção possui duas subseções. Uma subseção contendo o algoritmo com sua análise.
Outra contendo a prova de que o algoritmo é correto e a subestrutura ótima.
2. Solução através da Programação Dinâmica
A programação dinâmica é uma técnica utilizada na solução de problemas que possuem
subproblemas relacionados, ou seja, os subproblemas compartilham subproblemas. Uma
solução convencional trabalharia mais que o necessário, pois resolveria o mesmo
problema mais de uma vez. No caso da programação dinâmica utiliza-se como artifício
o armazenamento das soluções dos subproblemas, assim se o mesmo subproblema for
encontrado, não será necessário resolvê-lo novamente [Knuth, 1998].

2.1. Subestrutura Ótima


Uma característica marcante em um problema solucionável através da programação
dinâmica é a subestrutura ótima. Esta subestrutura representa as soluções ótimas para os
subproblemas e que são necessárias para se chegar a solução ótima do problema
principal. No caso do problema dos postos de combustível pode-se considerar que, para
qualquer parada presente na solução ótima, há uma subestrutura ótima antes da parada.
Isto é, se tomarmos uma parada qualquer em uma solução ótima, deve existir um
número mínimo de paradas para o subpercurso anterior [Brassard and Bratley 1998].

2.2. Expressão de Cálculo


Inicialmente pode-se imaginar uma matriz para armazenar todas as possíveis paradas de
um ponto a outro. No entanto, no problema em questão, o trajeto é feito em um único
sentido, assim é necessário armazenar somente as paradas do início até cada posto de
combustível.
Para resolver o problema dos postos de combustível considera-se a autonomia do
veículo; um vetor D, que contem as distâncias entre os postos; um vetor P, para
armazenar os números de paradas e um vetor DPUP, para armazenar a distância
percorrida desde a última parada até cada posto de combustível. Considera-se também
que um ponto no percurso pode ser qualquer posto ou o ponto de chegada. Desta
maneira, para determinar o número de paradas até o ponto i tem-se a expressão de
cálculo exibida na Figura 1.

0, se i ≤ 1
Pi Pi - 1 + 1, se DPUPi - 1 + Di - 1 > autonomia
Pi - 1

0, se i ≤ 1
DPUPi Di - 1 , se DPUPi - 1 + Di - 1 > autonomia
DPUPi – 1 + Di - 1

Figura 1: Expressão de cálculo para obter algoritmo de programação dinâmica

2.3. Algoritmo e Análise


Através da expressão de cálculo da Figura 1 é possível obter o algoritmo listado na
Figura 2. Pode-se verificar que, para o vetor P a primeira posição é preenchida com
zero, pois não há paradas do ponto inicial até ele mesmo, no vetor DPUP acontece o
mesmo, pois não há distância restante até o primeiro ponto. As demais posições destes
vetores são preenchidas de acordo com os valores já calculados e armazenados nas
posições anteriores.
algorithm paradas_dinamico(D, n, autonomia)
1. P1 ← 0
2. DPUP1 ← 0
3. for i ← 1 to n + 1
4. do if ( DPUPi - 1 + Di - 1 ) > autonomia
5. then Pi ← Pi – 1 + 1
6. DPUPi ← Di – 1

7. else Pi ← Pi – 1

8. DPUPi ← Di - 1 + Di – 1

9. return Pn + 1

Figura 2: Algoritmo para solucionar o problema dos postos de combustível


através de programação dinâmica

Os parâmetros de entrada do algoritmo paradas_dinamico descrito na Figura 2


são o vetor “D”, contendo as distâncias entre os postos de combustível; “n” que é o
número de postos existentes e “autonomia”, que é a distância máxima percorrida pelo
veículo após um abastecimento[Cormem, 2002].
Na análise do algoritmo da paradas_dinamico, constata-se a existência de um
laço que é executado n vezes. Logo, o tempo do algoritmo é O(n). Também deve-se
considerar o espaço ocupado para armazenar as respostas dos subproblemas, como são
utilizados dois vetores de tamanho n + 1 , o espaço ocupado será da ordem de O(n).
A solução retornada pelo algoritmo será o valor armazenado na posição n + 1 do
vetor P, que será a última posição a ser calculada pelo algoritmo.

3. Solução através de Algoritmos Gulosos


Os algoritmos gulosos resolvem problemas através de uma escolha gulosa, ou seja, é
realizada uma escolha interessante para o momento atual, na expectativa de que tal
escolha leve a uma solução ótima. A solução ótima pode não acontecer e o algoritmo
não funcionar, mas para muitos problemas há uma solução ótima por meio de
algoritmos gulosos trazendo uma enorme vantagem em relação a um algoritmo que
utiliza a força bruta [Cormem, 2002].

3.1. Algoritmo e análise


No problema dos postos de combustível a escolha gulosa de uma parada faz com que no
percurso restante haja o mínimo possível de paradas. Desta forma, tem-se o algoritmo
paradas_guloso, listado na Figura 3, para solucionar este problema.
algorithm paradas_guloso(D, n, autonomia)
1. p ← 0
2. ultima ← 0
3. for i ← 1 to n
4. do if (Di + ultima) > autonomia
5. then p ← p + 1
6. ultima ← Di
7. else ultima ← ultima + Di
8. return p
Figura 3: Algoritmo para solucionar o problema dos postos de combustível
através de algoritmos gulosos

Os parâmetros de entrada fornecidos para o algoritmo paradas_guloso são os


mesmos do algoritmo paradas_dinamico. E o seu tempo é O(n), pois há um laço na linha
3 que é executado n vezes.

3.2. Prova e subestrutura ótima


Como os algoritmos gulosos podem não funcionar, deve-se provar que o algoritmo
paradas_guloso funciona.
Teorema: O algoritmo paradas_guloso sempre encontra soluções de tamanho
mínimo para o problema dos postos de combustível.
Prova: Seja S={s1,s2,...sj} uma solução ótima qualquer e seja S' uma solução
encontrada pelo algoritmo paradas_guloso, cuja primeira parada de acordo com a
escolha gulosa é g1. Deve-se provar que S' é uma solução ótima de tamanho igual a S.
Se s1 = g1 então a solução S' é uma solução ótima. Se s1 ≠ g1, de acordo com a
escolha gulosa, tem-se que g1 está após s1. Assim, se S'={g1,s2,...sk}, chega-se a uma
solução de mesmo tamanho de S. A distância entre g1 e s2 não é maior que a distância
entre s1 e s2 e portanto o combustível será suficiente. Como o restante de S' é igual a S,
conclui-se que S' é uma solução ótima.
No problema dos postos de combustível é possível identificarmos a subestrutura
ótima, visto que a cada escolha gulosa resta um subproblema equivalente ao original,
mas com um número menor de paradas. Ou seja, em um problema P com solução S,
após uma parada em “g”, resta um subproblema P' com origem em “g”, cuja solução é
S'. Logo o a solução S do problema P é igual a solução S' do subproblema P' mais um.

4. Conclusão
Na análise dos algoritmos paradas_dinamico e paradas_guloso pode-se constatar que
possuem o mesmo tempo. O algoritmo paradas_guloso pode ser considerado melhor,
visto que no algoritmo paradas_dinamico é ocupado um espaço O(n). No entanto, se
modificarmos o algoritmo paradas_dinamico para retornar o vetor P como resposta,
consegue-se um resultado mais completo, já que o vetor P contém o número de paradas
para todos os percursos a partir do ponto inicial.
Os algoritmos apresentados através de programação dinâmica e da técnica gulosa
têm um tempo muito, isto é, polinomial. Um algoritmo que tente resolver o problema
dos postos de combustível através de força bruta, testando todas as possibilidades,
levaria um tempo muito maior, exponencial.
Pode-se constatar também que, no problema dos postos de combustível os
algoritmos construídos através de programação dinâmica e os algoritmos gulosos
possuem o mesmo tempo. Entretanto para a maioria dos problemas que possuem
solução através de algoritmos gulosos, tem-se um tempo menor do que em um
algoritmo que utiliza a programação dinâmica.

Referências
Cormen, T. H.; et al. (2002). “Algoritmos: Teoria e prática”, 2a ed. Rio de Janeiro:
Editora Campus.
Brassard, G. and Bratley, P. (1998). “Fundamentals of Algorithmics”. Prentice Hall of
India
Knuth, D. E. (1998). “The Art of Computer Programming”. Vol. 3 - Sorting and
Searching. Addison-Wesley.

Você também pode gostar