menor.pas
{ ppc386 -va -vh *.pas }
{ COMIENZO DE DESCRIPCION
Dada una lista de ciudades y una funci\'on DISTANCIA que
retorna la distancia entre dos ciudades dadas, busca el
camino de menor recorrido, utilizando un algoritmo
heur\ia istico. keywords: algoritmos
FIN DE DESCRIPCION }
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
{ $ Id: menor.pas 2002/04/05 14:20 mstorti Exp jdelia $}
program menor_recorrido_test ;
const
nnodos = 20;
chunk = 10000;
max_dis = 100 ;
type
tipo_elemento = integer;
tipo_celda = record
elemento : tipo_elemento;
sig : ^tipo_celda;
end;
lista = ^tipo_celda;
posicion = ^tipo_celda;
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
{ IMPLEMENTACION DE LISTAS }
procedure INSERTA( x : tipo_elemento;
p : posicion;
var L : lista);
var
temp : posicion;
nuevo : ^tipo_celda;
begin
temp := p^.sig;
new (nuevo);
p^.sig := nuevo;
nuevo^.elemento := x;
nuevo^.sig := temp;
end; {INSERTA}
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
function ANULA (var L : lista) : posicion;
begin
new (L);
L^.sig := nil;
ANULA := L;
end; {ANULA}
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
procedure IMPRIME (L : lista);
var
p : posicion;
q : ^tipo_celda;
begin
p := L;
writeln ('Lista: ');
q := p^.sig;
while q <> nil do begin
writeln (q^.elemento);
q := q^.sig;
end; {while}
writeln ('Fin de la lista');
end; {IMPRIME}
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
function PRIMERO (L : lista) : posicion;
begin
PRIMERO := L;
end;{PRIMERO}
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
procedure SUPRIME ( p : posicion;
var L : lista);
var
tmp : posicion;
begin
tmp := p^.sig;
p^.sig := tmp^.sig;
end; {SUPRIME}
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
function FIN (L : lista) : posicion;
var
q : posicion;
begin
q := L;
while (q^.sig <> nil) do q := q^.sig;
FIN := q;
end; { FIN }
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
function RECUPERA (p : posicion; L: lista): tipo_elemento;
var
tmp : posicion;
begin
tmp := p^.sig;
RECUPERA := tmp^.elemento;
end;
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
function SIGUIENTE (p : posicion; L: lista): posicion;
begin
SIGUIENTE := p^.sig;
end;
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
procedure COPIA (L1 : lista; var L2:lista);
var
p : posicion;
begin
ANULA (L2);
p := PRIMERO (L1);
while (p <> FIN (L1) ) do begin
INSERTA ( RECUPERA (p, L1), FIN (L2), L2);
p := SIGUIENTE (p,L1);
end; {while}
end; {COPIA}
{-----+-----+-----+ EJERCICIO +-----+-----+-----+-----+-----}
function DISTANCIA (a, b: integer): real;
var
bb : tipo_elemento;
begin
DISTANCIA := max_dis ;
bb := b + 1;
if (bb > nnodos) then bb := 1;
if (a = bb) then DISTANCIA := 1;
bb := b - 1;
if (bb = 0) then bb := nnodos;
if (a = bb) then DISTANCIA := 1;
end;
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
function MAS_CERCANO (no_visitado: lista;
ultima: tipo_elemento): posicion;
var
q, qmin: posicion;
c, cmin: tipo_elemento;
begin
qmin := PRIMERO (no_visitado);
q := SIGUIENTE (qmin, no_visitado);
while ( q <> FIN (no_visitado) ) do begin
c := RECUPERA (q,no_visitado);
cmin := RECUPERA (qmin, no_visitado);
if DISTANCIA (c,ultima) <
DISTANCIA (cmin,ultima) then qmin := q;
q := SIGUIENTE (q, no_visitado);
end ; {while}
MAS_CERCANO := qmin;
end;
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
procedure MENOR_RECORRIDO (var camino: lista;
ciudades: lista);
var
p : posicion;
c, ultima, primera : tipo_elemento;
no_visitado : lista;
begin
{Inicializa camino}
ANULA (camino);
{Copia 'ciudades' en 'no_visitado' }
ANULA (no_visitado);
p := PRIMERO (ciudades);
while ( p <> FIN (ciudades) ) do begin
c := RECUPERA (p, ciudades);
INSERTA (c, FIN (no_visitado), no_visitado);
p := SIGUIENTE (p, ciudades);
end; {while}
{Mueve primera ciudad en 'no_visitado' a 'camino'}
p := PRIMERO (no_visitado);
c := RECUPERA (p, no_visitado);
INSERTA (c, PRIMERO (camino), camino);
SUPRIME (p, no_visitado);
ultima := c;
primera := c;
while PRIMERO (no_visitado) <> FIN (no_visitado) do begin
p := MAS_CERCANO (no_visitado, ultima);
ultima := RECUPERA (p, no_visitado);
INSERTA (ultima, FIN (camino), camino);
SUPRIME (p,no_visitado);
end; {while}
{Inserta la primera al final para que el camino sea cerrado}
INSERTA (primera, FIN (camino), camino);
end; { MENOR_RECORRIDO }
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
procedure ORDENA_ALEATORIO (var L : lista);
var
n, i, j, k: integer;
p : posicion;
auxiliar : lista;
c : tipo_elemento;
begin
{Cuenta cuantos elementos hay en la lista}
{y pasa todos los elementos a 'auxiliar', 'L' queda vacia}
n := 0;
p := PRIMERO (L);
ANULA (auxiliar);
while (p <> FIN (L) ) do begin
INSERTA ( RECUPERA (p,L), FIN (auxiliar), auxiliar);
SUPRIME (p,L);
n := n + 1;
end; {while}
{Va tomando elementos al azar de 'auxiliar' y los pone en 'L'}
for i := 1 to n do begin
j := TRUNC (RANDOM * (n - i + 1)) + 1;
p := PRIMERO (auxiliar);
for k := 1 to (j - 1) do p := SIGUIENTE (p, auxiliar);
c := RECUPERA (p, auxiliar);
SUPRIME (p, auxiliar);
INSERTA (c, FIN (L),L);
end ; {i}
end; {ORDENA_ALEATORIO}
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
function CALCULA_RECORRIDO (camino: lista): real;
var
dist : real;
p : posicion;
c, cc : tipo_elemento;
begin
dist := 0;
p := PRIMERO (camino);
c := RECUPERA (p, camino);
p := SIGUIENTE (p, camino);
while (p <> FIN (camino) ) do begin
cc := RECUPERA (p,camino);
dist := dist + DISTANCIA (c,cc);
c := cc ;
p := SIGUIENTE (p,camino);
end ; {while}
CALCULA_RECORRIDO := dist;
end; {CALCULA_RECORRIDO}
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
var
ciudades, camino, aleatorio : lista;
i, k : integer;
dmin, d : real;
pri : tipo_elemento;
begin
ANULA (ciudades);
for i := 1 to nnodos do begin
INSERTA (i, FIN (ciudades), ciudades);
end ; {for}
writeln ('Orden inicial de las ciudades');
IMPRIME (ciudades);
{Pone las ciudades en forma aleatoria en ciudades}
ORDENA_ALEATORIO (ciudades);
writeln ('Despues de desordenar');
IMPRIME (ciudades);
MENOR_RECORRIDO (camino,ciudades);
writeln ('menor camino');
IMPRIME (camino);
writeln ('Distancia recorrida en el camino: ',
CALCULA_RECORRIDO (camino));
dmin := 1.0e6;
k := 0;
while (true) do begin
k := k + 1;
if (k = chunk) then begin
writeln (chunk,' ejecutados...');
k := 2;
end ; {if}
COPIA (ciudades, aleatorio);
ORDENA_ALEATORIO (aleatorio);
pri := RECUPERA (PRIMERO (aleatorio), aleatorio);
INSERTA ( pri, FIN (aleatorio), aleatorio);
d := CALCULA_RECORRIDO (aleatorio);
if (k = 1) or (d < dmin) then begin
writeln('distancia mas corta:',d);
IMPRIME (aleatorio);
dmin := d;
end; {if}
end; {while}
end.
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
Generated by GNU enscript 1.6.1.