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