Solucion - Universidad Politécnica de Madrid

Anuncio
Dpto. O.E.I. – U.P.M.
ALGORÍTMICA
17/ENE/12
1º) (3’5 Puntos) Se dispone de una matriz con N × M números enteros. Se pide: Desarrollar un
algoritmo en Pascal que determine el conjunto mínimo de elementos de la matriz cuya suma sea un
determinado valor X.
CONST
N = 4;
M = 3;
NporM = 12;
TYPE
TIndice1 = 1..N;
TIndice2 = 1..M;
TTablero = ARRAY[TIndice1, TIndice2] OF Integer;
TPosicion = RECORD
X: TIndice1;
Y: TIndice2
END;
TSolucion = RECORD
Pasos : ARRAY [1..NporM] OF TPosicion;
Ultimo: 0..NporM;
END;
VAR
Tablero: TTablero;
Solucion, MejorSolucion: TSolucion;
Correcto: Boolean;
Paso: Integer;
PROCEDURE CopiarVector(Solucion: TSolucion; VAR MejorSolucion: TSolucion);
VAR
I: Integer;
BEGIN
MejorSolucion.ultimo := Solucion.ultimo;
FOR I := 1 TO Solucion.ultimo DO BEGIN
MejorSolucion.Pasos[I].X := Solucion.Pasos[I].X;
MejorSolucion.Pasos[I].Y := Solucion.Pasos[I].Y
END
END; (* CopiarVector *)
PROCEDURE Anotar(VAR Tablero:TTablero; X: TIndice1; Y: TIndice2; VAR Solucion: TSolucion);
VAR
Aux: Integer;
BEGIN
WITH Solucion DO BEGIN
Ultimo := Ultimo + 1;
Pasos[Ultimo].X := X;
Pasos[Ultimo].Y := Y;
END;
END; (* Anotar *)
PROCEDURE DesAnotar(VAR Tablero: TTablero; X: TIndice1; Y: TIndice2; VAR Solucion: TSolucion);
VAR
Aux : Integer;
BEGIN
Solucion.Ultimo := Solucion.Ultimo - 1;
END; (* Desanotar *)
PROCEDURE Escribir_Solucion(Tablero: TTablero; Solucion: TSolucion);
VAR
I, J: Integer;
BEGIN
J := 1;
WriteLn('La Solucion tiene pasos = ', Solucion.Ultimo);
WITH Solucion DO
FOR I:=1 TO Ultimo DO BEGIN
WriteLn('(', Pasos[I].X, ' ', Pasos[I].Y, ')');
J := J + 1;
END
END; (* Escribir_Solucion *)
Universidad Politécnica de Madrid – E.U. Informática
Página 1
PROCEDURE Ensayar(VAR Tablero: TTablero; Paso: Integer; Valor: Integer;
VAR Solucion, MejorSolucion: TSolucion; VAR Correcto: Boolean);
VAR
I: Integer; Nx: TIndice1; Ny: TIndice2;
BEGIN
FOR I := Paso TO NporM DO BEGIN
Nx := (I - 1) DIV M + 1;
Ny := (I - 1) MOD M + 1;
Anotar(Tablero, Nx, Ny, Solucion);
IF (Valor - Tablero[Nx, Ny]) = 0 THEN
IF NOT Correcto THEN BEGIN
Correcto := true;
CopiarVector(Solucion,MejorSolucion);
END
ELSE BEGIN
IF Solucion.ultimo < MejorSolucion.ultimo THEN
CopiarVector(Solucion,MejorSolucion);
END
ELSE
Ensayar(Tablero, I + 1, Valor - Tablero[Nx, Ny], Solucion, MejorSolucion, Correcto);
DesAnotar(Tablero, Nx, Ny, Solucion)
END
END; (* Ensayar *)
BEGIN (* PROGRAMA PRINCIPAL *)
…
Correcto := False;
Solucion.Ultimo := 0;
MejorSolucion.Ultimo := 0;
Ensayar(Tablero, 1, 5, Solucion, MejorSolucion, Correcto);
IF Correcto THEN
Escribir_Solucion(Tablero, MejorSolucion)
ELSE
Writeln('No hay solucion');
END.
Universidad Politécnica de Madrid – E.U. Informática
Página 2
2º) (3’5 Puntos) Se dispone de un grafo no dirigido que representa la distancia entre distintas
ciudades y los posibles medios de transporte (avión, coche o bicicleta). Teniendo en cuenta que la
distancia es independiente del medio de transporte empleado, se pide: codificar un algoritmo en
Pascal que determine el camino mínimo para ir desde una ciudad origen a una ciudad destino de
manera que nunca se emplee el avión como medio de transporte.
NOTA: Como siempre, se deberá prestar atención a la complejidad de la solución desarrollada.
Para resolver el problema se dispondrá de una matriz de costes con las conexiones entre las diferentes
ciudades. Si existe conexión, la distancia siempre es menor que 1000. Si la conexión es por bicicleta,
vendrá codificada como 1XXX, si la conexión es por coche estará codificada como 1XXXX, y si existe
conexión por avión será 1XXXXX. Las ciudades que no estén conectadas por ningún medio tendrán
asignada la constante infinito en la posición correspondiente de la matriz.
Ejemplo: 10324 indica que hay una distancia de 324 km., y que sólo se puede emplear el coche.
CONST
Infinito = 999999;
NoVisitado = -1;
TYPE
TVertice = 1..N;
TGrafo = ARRAY [TVertice, TVertice] OF LongInt;
TVertices = ARRAY [TVertice] OF TVertice;
TMenorCoste = ARRAY [TVertice] OF LongInt;
TVisitados = ARRAY [TVertice] OF Boolean;
PROCEDURE Inicializar(Coste: TGrafo; VAR MenorCoste: TMenorCoste; Origen: TVertice;
VAR VAnterior: TVertices; VAR Visitados: TVisitados);
VAR
I: TVertice;
BEGIN
FOR I := 1 TO N DO BEGIN
VAnterior[I] := NoVisitado;
Visitados[I] := (I = Origen);
IF
Coste[Origen, I] <> Infinito
THEN MenorCoste[I] := Coste[Origen, I] MOD 1000;
ELSE MenorCoste[I] := Infinito;
END;
VAnterior[Origen] := Origen;
END; (* Inicializar *)
FUNCTION Seleccionar_Vertice_MenorCoste(MenorCoste: TMenorCoste; Visitados: TVisitados): Integer;
VAR
I: TVertice;
Minimo: Real;
BEGIN
Minimo := Infinito;
Vertice := NoVisitado;
FOR I := 1 TO N DO
IF (MenorCoste[I] < Minimo) AND (NOT Visitados[I]) THEN BEGIN
Minimo := MenorCoste[I];
Vertice := I
END;
Seleccionar_Vertice_MenorCoste := Vertice
END; (* Seleccionar_Vertice_MenorCoste *)
PROCEDURE Escribir_Camino(VAnterior: TVertices; Origen, Destino:TVertice);
BEGIN
IF Origen <> Destino THEN BEGIN
Escribir_Camino(VAnterior, Origen, VAnterior[Destino]);
Write(', ', Destino);
END
ELSE
Write(Origen)
END; (* Escribir_Camino *)
Universidad Politécnica de Madrid – E.U. Informática
Página 3
PROCEDURE Dijkstra(Coste:TGrafo; Origen: TVertice; VAR VAnterior: TVertices);
VAR
I, J, Vertice: TVertice;
Visitados: TVisitados;
MenorCoste: TMenorCoste;
BEGIN
Inicializar(Coste, MenorCoste, Origen, VAnterior, Visitados);
FOR I := 2 TO N DO BEGIN
Vertice := Seleccionar_Vertice_MenorCoste(MenorCoste, Visitados);
IF Vertice <> NoVisitado
THEN BEGIN
Visitados[Vertice] := True;
FOR J := 1 TO N DO
(* se descarta cuando sólo hay avión 100XXX *)
IF (NOT Visitados[J]) AND (Coste[Vertice, J] < 100000 OR Coste[Vertice, J] > 101000)
THEN IF
MenorCoste[J] > MenorCoste[Vertice] + (Coste[Vertice, J] MOD 1000)
THEN BEGIN
MenorCoste[J] := MenorCoste[Vertice] + (Coste[Vertice, J] MOD 1000));
VAnterior[J] := Vertice
END
END
END; (* Dijkstra *)
PROCEDURE CaminoMinimo(Coste:TGrafo; Origen, Destino: TVertice);
VAR
MenorCoste: TMenorCoste;
VAnterior: TVertices;
BEGIN
Dijkstra(Coste, Origen, VAnterior);
IF
VAnterior[Destino] = NoVisitado
THEN WriteLn('No hay camino entre los vértices')
ELSE Escribir_Camino(VAnterior, Origen, Destino)
END; (* CaminoMinimo *)
BEGIN
…
CaminoMinimo(Coste, Origen, Destino)
END.
Universidad Politécnica de Madrid – E.U. Informática
Página 4
3º) (3 Puntos) Dado un vector de tamaño N que contiene números enteros, se pide: siguiendo
el esquema Divide y Vencerás, desarrollar en lenguaje Pascal un algoritmo que determine la
longitud de la secuencia estrictamente creciente más larga.
3
2
7
4
8
4
6
7
2
5
En el ejemplo, la longitud de la secuencia más larga es 3 (subsecuencia 4, 6, 7).
CONST
N = 6;
TYPE
TIndice = 1..N;
TVector = ARRAY [TIndice] OF Integer;
VAR
Vector: TVector;
MaximoIzq, MaximoDer: Integer;
FUNCTION DyV(Vector: TVector; Izq, Der: Integer; VAR MaxIzquierda, MaxDerecha: Integer): Integer;
VAR
MaxDerecha1, MaxIzquierda1,
MaxDerecha2, MaxIzquierda2,
Max1, Max2, Medio, Maximo: Integer;
Creciente : Boolean;
BEGIN
IF (Izq = Der) THEN BEGIN
MaxIzquierda := 1;
MaxDerecha := 1;
DyV := 1;
END
ELSE BEGIN
Medio := (Izq + Der) DIV 2;
Max1 := DyV(Vector, Izq, Medio, MaxIzquierda1, MaxDerecha1);
Max2 := DyV(Vector, Medio + 1, Der, MaxIzquierda2, MaxDerecha2);
IF Max1 > Max2 THEN
Maximo := Max1
ELSE
Maximo := Max2;
Creciente := Vector[Medio] <= Vector[Medio + 1];
IF Creciente AND ((MaxDerecha1 + MaxIzquierda2) > Maximo) THEN
Maximo := MaxDerecha1 + MaxIzquierda2;
IF Creciente AND ((Medio - Izq + 1) = MaxIzquierda1) THEN
MaxIzquierda := MaxIzquierda1 + MaxIzquierda2
ELSE
MaxIzquierda := MaxIzquierda1;
IF Creciente AND ((Der - Medio) = MaxDerecha2) THEN
MaxDerecha := MaxDerecha1 + MaxDerecha2
ELSE
MaxDerecha := MaxDerecha2;
DyV := Maximo
END
END; (* DyV *)
BEGIN
…
WriteLn('Longitud máxima de secuencia creciente = ', DyV(vector, 1, N, MaximoIzq, MaximoDer));
END.
Universidad Politécnica de Madrid – E.U. Informática
Página 5
Descargar