Solución - Universidad Politécnica de Madrid

Anuncio
ALGORÍTMICA
Dpto. O.E.I. – U.P.M.
2/SEP/09
1º) (3'5 Puntos) El Marshall de un torneo de golf es la persona que asiste a los
jugadores, conservando el buen flujo de los mismos en el campo y aplicando el
reglamento. Como preparación previa al torneo se encarga de revisar el estado de los
hoyos y verificar el color de cada bandera, lo que indica por lo general la posición de la
bandera en el green o sea, si esta adelante (roja), en el medio (blanca), o atrás (azul).
SE PIDE: Escribir un algoritmo en Pascal que calcule cuál es la ruta que debe seguir el
Marshall para realizar la verificación de todas las banderas de los 18 hoyos, realizando el
menor recorrido posible. El esquema de hoyos del campo está representado por un grafo
no dirigido valorado implementado con una matriz de valores que indican el número de
metros existentes entre los hoyos, pudiendo ser MAXINT si no hay camino entre los
hoyos. NOTA: el Marshall parte del hoyo 1 y finaliza su recorrido en el hoyo 1.
CONST
NMax = 18; (* Número máximo hoyos recorrido *)
FichRecorrido = 'campo18.txt'; Infinito = 10000;
DistanciaMaxima = 2000; (* Distancia máxima que se puede recorrer *)
TYPE
tRecorrido = ARRAY [1..NMax, 1..NMax] OF Integer; (* Matriz con distancias entre hoyos *)
tVector = ARRAY [1..NMax] OF Integer;
tPila = ^Registro;
Registro = RECORD
hoyo: Integer;
sig: tPila
END;
VAR
Recorrido: tRecorrido;
Comprobado: tVector;
v, N, distOptima: Integer;
Camino, CaminoOpt: tPila;
PROCEDURE IniPila(VAR P: tPila);
BEGIN
P := NIL;
END; (* IniPila *)
FUNCTION PilaVacia(P: tPila): Boolean;
BEGIN
PilaVacia := (P = NIL)
END; (* PilaVacia *)
PROCEDURE Apilar(VAR P: tPila; hoyo: Integer);
VAR aux: tPila;
BEGIN
NEW(aux);
aux^.hoyo := hoyo;
aux^.sig := P;
P := aux;
END; (* Apilar *)
PROCEDURE Desapilar(VAR P: tPila; VAR hoyo: Integer);
VAR aux: tPila;
BEGIN
IF PilaVacia(P) THEN WriteLn('ERROR: Pila Vac¡a')
ELSE BEGIN
hoyo := P^.hoyo;
aux := P;
P := P^.sig;
Dispose(aux);
END
END; (* Desapilar *)
PROCEDURE VaciarPila(VAR P: tPila);
VAR aux: Integer;
BEGIN
WHILE NOT PilaVacia(P) DO Desapilar(P, aux)
END; (* Vaciar Pila *)
PROCEDURE CopiarPila(VAR pOrigen, pDestino: tPila);
VAR hoyo: Integer;
BEGIN
IF NOT PilaVacia(pOrigen) THEN BEGIN
Desapilar(pOrigen, hoyo);
CopiarPila(pOrigen, pDestino);
Apilar(pOrigen, hoyo);
Apilar(pDestino, hoyo);
END
END; (* CopiarPila *)
PROCEDURE CargarMatrizDistancias(VAR Recorrido: tRecorrido);
VAR Fichero: Text; h1, h2, dist: Integer;
BEGIN
FOR h1 := 1 TO NMax DO
FOR h2 := 1 TO NMax DO Recorrido[h1][h2] := Infinito;
FOR h1 := 1 TO NMax DO Recorrido[h1][h1] := 0;
Universidad Politécnica de Madrid – E.U. Informática Página 1 assign(Fichero, FichRecorrido);
Reset(Fichero);
ReadLn(Fichero, N);
WHILE NOT EoF(Fichero) DO BEGIN
ReadLn(Fichero, h1, h2, dist);
IF
(h1 < 0) OR (h1 > N) OR (h2 < 0) OR (h2 > N) OR (dist < 0)
THEN WriteLn('Error en lectura de datos', h1, h2, dist);
Recorrido[h1][h2] := dist;
Recorrido[h2][h1] := dist;
END;
Close(Fichero)
END; (* CargarMatrizDistancias *)
(* Recorrido Comprobado -> todos distinto 0 *)
FUNCTION RecorridoComprobado(Comprobado: tVector): Boolean;
VAR v: Integer; TodosDistintosCero: Boolean;
BEGIN
v := 2;
TodosDistintosCero := TRUE;
WHILE (v <= N) AND TodosDistintosCero DO BEGIN
TodosDistintosCero := (Comprobado[v] <> 0);
v := v + 1
END;
RecorridoComprobado := TodosDistintosCero
END; (* RecorridoComprobado *)
(* Algoritmo de selección óptima *)
PROCEDURE ComprobarBanderas(VAR Recorrido: tRecorrido; (* se pasa por ref. para ahorrar memoria *)
hoyoActual, distanciaMaxima, distActual: Integer;
VAR distOptima: Integer; VAR Comprobado: tVector; VAR Camino, CaminoOpt: tPila);
VAR aux, hoyoSig: Integer;
BEGIN
FOR hoyoSig := 1 TO N DO
IF (Recorrido[hoyoActual][hoyoSig] + distActual <= distanciaMaxima) AND (hoyoSig <> hoyoActual)
THEN BEGIN
Comprobado[hoyoSig] := Comprobado[hoyoSig] + 1;
Apilar(Camino, hoyoSig);
distActual := distActual + Recorrido[hoyoActual][hoyoSig];
IF
(hoyoSig = 1) AND RecorridoComprobado(Comprobado) AND (distActual < distOptima)
THEN BEGIN
distOptima := distActual;
VaciarPila(CaminoOpt);
CopiarPila(Camino, CaminoOpt);
WriteLn('Solucion =', distOptima);
END
ELSE IF distActual < distOptima
THEN ComprobarBanderas(Recorrido, hoyoSig, distanciaMaxima, distActual, distOptima,
Comprobado, Camino, CaminoOpt);
Comprobado[hoyoSig] := Comprobado[hoyoSig] - 1;
Desapilar(Camino, aux);
distActual := distActual - Recorrido[hoyoActual][hoyoSig];
END
END; (* ComprobarBanderas *)
PROCEDURE ImprimirCamino(VAR Camino: tPila);
VAR aux: Integer;
BEGIN
IF NOT PilaVacia(Camino) THEN BEGIN
Desapilar(Camino, aux);
ImprimirCamino(Camino);
Apilar(Camino, aux);
Write(aux, ' ')
END
END; (* ImprimirCamino *)
BEGIN
CargarMatrizDistancias(Recorrido);
WriteLn('Número de hoyos = ', N);
(* Inicializamos el vector con todos los hoyos sin comprobar, salvo el 1 *)
FOR v := 2 TO NMax DO Comprobado[v] := 0;
Comprobado[1] := 1;
IniPila(CaminoOpt);
IniPila(Camino);
Apilar(Camino, 1);
distOptima := Infinito;
ComprobarBanderas(Recorrido, 1, distanciaMaxima, 0, distOptima, Comprobado, Camino, CaminoOpt);
IF
distOptima = Infinito
(* No se ha encontrado ninguna solución *)
THEN WriteLn('No hay solución')
ELSE BEGIN
ImprimirCamino(CaminoOpt);
WriteLn('Distancia Óptima: ', distOptima)
END
END.
Universidad Politécnica de Madrid – E.U. Informática Página 2 2º) (3'5 Puntos) El software del proyecto "Hubble Space Telescope Key Project" genera un
vector sin ordenación previa, denominado vector de distancias estelares, que recoge las
distancias precisas de la mayor parte de los objetos estelares de nuestra galaxia. La
participación española al proyecto no ha sido muy acertada puesto que debía encargarse
de calcular la moda de dichos valores (valor esencial requerido para determinar la edad,
el tamaño y el destino del universo) y debido a un problema de sincronización lo que han
obtenido es un vector, denominado vector de posibles modas, que contiene 3 posibles
valores para la moda.
SE PIDE: Implementar un algoritmo en Pascal que indique cuál de los 3 valores alojados
en el vector de posibles modas es realmente la moda de los valores alojados en el vector
de distancias estelares. NOTA: No se permite la utilización de bucles. La MODA es el valor
de la variable que más veces se repite, es decir, aquella cuya frecuencia absoluta es
mayor. No tiene por qué ser única.
Usando el esquema DyV vamos a contar el número de ocurrencias de los tres valores del vector VPM en el
vector VDE.
PROGRAM Ejercicio2;
CONST
N = 24;
TYPE
tIndice = 1..N;
tVDE = ARRAY[tIndice] OF Integer;
tVPM = ARRAY[1..3] OF Integer;
VAR
VDE: tVDE;
VPM, VFrecuencias: tVPM;
Mayor : Integer;
PROCEDURE Inicializa(VAR VDE: tVDE; VAR VPM: tVPM);
BEGIN
(*5, 4, 5, 7, 5, 5, 10, 10, 10, 5, 2, 5, 5, 5, 10, 10, 10, 5, 10, 1, 10, 1, 10, 1*)
VDE[1]:= 5; VDE[2]:= 4; VDE[3]:= 5; ..... VDE[23]:= 10; VDE[24]:= 1;
VPM[1]:=5; VPM[2]:=1;
VPM[3]:=10;
END;
PROCEDURE ObtenerFrecuenciasDyV (VDE: tVDE; inicio, fin: tIndice; VAR VFrecuencias: tVPM);
VAR
VFrecuenciasI, VFrecuenciasD: tVPM;
medio : Integer;
BEGIN
IF (fin-inicio=0) THEN
BEGIN
VFrecuencias[1]:=0; VFrecuencias[2]:=0; VFrecuencias[3]:=0;
IF VDE[inicio]=VPM[1] THEN VFrecuencias[1]:=1;
IF VDE[inicio]=VPM[2] THEN VFrecuencias[2]:=1;
IF VDE[inicio]=VPM[3] THEN VFrecuencias[3]:=1;
END
ELSE
BEGIN
medio := (fin+inicio) DIV 2;
ObtenerFrecuenciasDyV(VDE, inicio, medio, VFrecuenciasI);
ObtenerFrecuenciasDyV (VDE, medio+1, fin, VFrecuenciasD);
VFrecuencias[1]:= VFrecuenciasI[1]+VFrecuenciasD[1];
VFrecuencias[2]:= VFrecuenciasI[2]+VFrecuenciasD[2];
VFrecuencias[3]:= VFrecuenciasI[3]+VFrecuenciasD[3];
END;
END;
Universidad Politécnica de Madrid – E.U. Informática Página 3 PROCEDURE ImprimeModas(vFrecuencias: tVPM; Mayor: Integer);
BEGIN
write('las modas del vector de distancias son los valores:');
IF vFrecuencias[1]=Mayor THEN write(VPM[1], ' ');
IF vFrecuencias[2]=Mayor THEN write(VPM[2], ' ');
IF vFrecuencias[3]=Mayor THEN write(VPM[3]);
writeln('
');
writeln('Pulse cualquier tecla para finalizar');
readln;
END;
BEGIN
Inicializa(VDE, VPM);
ObtenerFrecuenciasDyV (VDE, 1, N, vFrecuencias);
IF (vFrecuencias[1]>=vFrecuencias[2]) AND (vFrecuencias[1]>=vFrecuencias[3])
THEN Mayor:= vFrecuencias[1]
ELSE IF (vFrecuencias[2]>=vFrecuencias[1]) AND (vFrecuencias[2]>=vFrecuencias[3])
THEN Mayor:= vFrecuencias[2]
ELSE Mayor:= VFrecuencias[3];
ImprimeModas(vFrecuencias, Mayor);
END.
Universidad Politécnica de Madrid – E.U. Informática Página 4 3º) (3 Puntos) Dados un tablero de ajedrez en el que todas casillas tienen asignados
valores aleatorios, una casilla inicial (Xi, Yi) y una casilla final (Xf, Yf).
SE PIDE: Desarrollar un algoritmo en Pascal que determine
si es posible que un caballo consiga llegar desde la casilla
inicial a la final cumpliendo la siguiente regla: cada
movimiento constará de dos pasos paseo y salto. El paseo se
inicia lanzando un dado y moviendo el caballo tantas
posiciones como indique el dado (el movimiento será de
derecha a izquierda y de arriba hacia abajo). Una vez
finalizado el paseo comenzará el salto, para lo que se obtendrá
el módulo 8 del valor de la casilla en la que esté situado el
caballo, que nos indicará el salto a realizar (los saltos del
caballo siguen la numeración indicada en la imagen). NOTA: Si el destino de un salto no
se encuentra dentro del tablero, no será considerado, pasándose de nuevo a lanzar el
dado. Si el destino de un paseo no se encuentra dentro del tablero, no será considerado.
En cada nivel de bactraking se genera un movimiento del caballo (un paseo más un salto). Dada la celda en
la que se encuentra actualmente el caballo existen hasta 6 posibles movimientos (paseo más salto), que se
corresponden con los 6 posibles valores del dado.
Un movimiento es aceptable si el paseo se encuentra dentro del tablero y el destino final del caballo (bien
sea sólo el destino del paseo, si el salto se sale del tablero, o el destino del salto si no se sale) no ha sido ya
visitado. Si ha sido visitado previamente no es válido, ya que se entraría en un bucle infinito de llamadas
recursivas.
Anotar implica modificar la celda actual del caballo. Hay dos posibilidades (teniendo en cuenta que a este
punto se llega después de un movimiento aceptable): que el salto esté dentro del tablero o no. Además, se
deberá marcar la celda destino del caballo como visitada.
Se llegará a una solución del problema si la celda actual del caballo después del movimiento actual es la
celda destino del juego.
Desanotar es el movimiento contrario a anotar.
PROGRAM Problema3;
CONST
N=7;
M=100;
TYPE
TIndice = 1..N;
TCoordenadas = 1..8;
TTablero = ARRAY[TIndice, TIndice] OF Integer;
TVisitados = ARRAY[TIndice, TIndice] OF boolean;
TDesplazamiento = ARRAY[TCoordenadas] OF -2..2;
TPosicion = RECORD
X,Y:TIndice;
END;
VAR
Tablero: TTablero;
Visitados : TVisitados;
DespX, DespY: TDesplazamiento;
solucion : boolean;
Pos, CasIni, CasFin : TPosicion; {posición del caballo, casilla inicial y casilla final}
PROCEDURE Inicializar_Desplazamiento(VAR DespX, DespY: TDesplazamiento);
BEGIN
DespX[1]:=-1; DespX[2]:=-2; DespX[3]:=-2; DespX[4]:=-1; DespX[5]:=1; DespX[6]:=2; DespX[7]:=2; DespX[8]:=1;
DespY[1]:=-2; DespY[2]:=-1; DespY[3]:=1; DespY[4]:=2; DespY[5]:=2; DespY[6]:=1; DespY[7]:=-1; DespY[8]:=-2;
END;
Universidad Politécnica de Madrid – E.U. Informática Página 5 PROCEDURE InicializarTablero(VAR Tablero:TTablero; VAR Visitados:TVisitados);
VAR
i,j:integer;
BEGIN
FOR i:=1 TO N DO
FOR j:=1 TO N DO
BEGIN
Tablero[i,j]:= Random(M);
Visitados[i,j]:= false;
END;
END;
PROCEDURE Ensayar(VAR Tablero:TTablero; VAR Visitados: TVisitados; Pos:TPosicion; VAR solucion:boolean);
VAR
NPos, NPos2: TPosicion;
dado, s: Integer;
BEGIN
dado:=0;
REPEAT
dado:=dado+1;
(*generamos el paseo*)
IF (Pos.Y-dado)>0 THEN BEGIN (*el paseo no genera salto a la siguiente fila*)
NPos.Y:=Pos.Y-dado;
NPos.X:= Pos.X;
END
ELSE BEGIN (*el paseo genera salto a la siguiente fila*)
NPos.X:=Pos.X+1;
NPos.Y:= N - (dado-Pos.Y);
END;
IF (NPos.X<=N) THEN (*paseo aceptable, no se sale del tablero*)
BEGIN
s:=(Tablero[NPos.X, NPos.Y] MOD 8)+1;
NPos2.X:= NPos.X + DespX[s];
NPos2.Y:= NPos.Y + DespY[s];
IF (NPos2.X >= 1)AND (NPos2.X <= N) AND (NPos2.Y >= 1) AND (NPos2.Y <= N) THEN
BEGIN (*el salto es aceptable, no se sale del tablero*)
NPos.X:=NPos2.X;
NPos.Y:=NPos2.Y;
END
IF NOT Visitados[NPos.X, NPos.Y] THEN (*Con esto se evitan las posibles llamadas recursivas infinitas*)
BEGIN
Visitados[NPos.X, NPos.Y] := true;
IF (NPos.X=CasFin.X) AND (NPos.Y=CasFin.Y) THEN solucion:=true;
ELSE BEGIN
Ensayar(Tablero, Visitados, NPos, solucion);
IF NOT solucion THEN Visitados[NPos.X, NPos.Y]:=false;
END;
END
END;
UNTIL (dado=6) OR solucion;
END;
BEGIN
CasIni.X:=2; CasIni.Y:=5; CasFin.X:=2; CasFin.Y:=2; Pos.X:=CasIni.X; Pos.Y:=CasIni.Y; solucion:=false;
InicializarTablero(Tablero, Visitados);
Visitados[CasIni.X, CasIni.Y]:=true;
Inicializar_Desplazamiento(DespX,DespY);
Ensayar(Tablero, Visitados, Pos, solucion);
IF NOT solucion THEN write ('No hay solucion')
ELSE write(‘Hay solución’)
END.
Universidad Politécnica de Madrid – E.U. Informática Página 6 
Descargar