Dpto. O.E.I. – U.P.M. ALGORÍTMICA 08/JUN/12 1º) (3’5 Puntos) Dado un array que contiene N números naturales diferentes mayores que cero, y un número X, se pide: Se pide: desarrollar en Pascal una función que determine el número total de subconjuntos diferentes cuya suma de sus elementos sea precisamente X. CONST N = 10; TYPE tVector = ARRAY [1..N] OF Integer; VAR V: tVector; numSoluciones, X: Integer; FUNCTION doSSXS(VAR V: tVector; X, actual, acumulado: Integer): Integer; (* El vector se pasa por referencia exclusivamente para ahorrar memoria *) VAR i, numSoluciones: Integer; BEGIN numSoluciones := 0; FOR i := actual TO N DO IF V[i] + acumulado <= X THEN BEGIN V[i] := -V[i]; (* anotar (se hace sólo para mostrar el subconjunto) *) IF acumulado - V[i] = X THEN NumSoluciones := NumSoluciones + 1 ELSE NumSoluciones := NumSoluciones + doSSXS(V, X, i + 1, acumulado - V[i]); V[i] := -V[i] (* desanotar *) END; doSSXS := numSoluciones END; (* doSSXS *) FUNCTION SubSetXSum(V: tVector; X: Integer): Integer; BEGIN SubSetXSum := doSSXS(V, X, 1, 0) END; (* SubSetSum *) Universidad Politécnica de Madrid – E.U. Informática Página 1 2º) (3’5 Puntos) Dado un grafo dirigido valorado (GDV) y un vector que contiene un valor asociado a cada uno de los nodos de dicho grafo, se dice que un nodo es "neutral" si el valor asociado al nodo en el vector es igual a la suma de los costes de los arcos entrantes y salientes en dicho nodo. Se dice que un GDV es "equilibrado" si existe una cadena entre cada par de vértices del mismo y además todos sus nodos son "neutrales". Se pide: desarrollar un algoritmo en Pascal que determine si un GDV representado por listas de adyacencia es "equilibrado". NOTA: Como siempre, se deberá prestar atención a la complejidad de la solución desarrollada. 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 recalculaValores(VAR Valores: tValores; GDV: tGrafo); VAR i: Integer; Aux: tListaAdy; BEGIN (* descuenta los valores de los costes de los arcos *) FOR i := 1 TO N DO BEGIN Aux := GDV[i]; WHILE (Aux <> NIL) DO BEGIN Valores[i] := Valores[i] - Aux^.Coste; (* arco saliente *) Valores[Aux^.Adyacente] := Valores[Aux^.Adyacente] - Aux^.Coste; Aux := Aux^.Sig END END END; (* recalculaValores *) (* arco entrante *) FUNCTION Conectado(GDV: tGrafo; Origen, Destino: tVertice): Boolean; VAR Encontrado: Boolean; Aux: tListaAdy; BEGIN Encontrado := False; Aux := GDV[Origen]; WHILE NOT Encontrado AND (Aux <> NIL) DO BEGIN Encontrado := (Aux^.Adyacente = Destino); Aux := Aux^.Sig END; Conectado := Encontrado END; (* Conectado *) PROCEDURE Visitar2(Origen: tVertice; GDV: tGrafo; VAR Visitados: tVisitados); VAR i: tVertice; BEGIN Visitados[Origen] := True; FOR i := 1 TO N DO IF Not Visitados[i] AND (Conectado(GDV, Origen, i) OR Conectado(GDV, i, Origen)) THEN Visitar2(i, GDV, Visitados) END; (* Visitar2 *) Universidad Politécnica de Madrid – E.U. Informática Página 2 FUNCTION TodosVisitadosYNeutrales(Visitados: tVisitados; Valores: tValores):Boolean; VAR i:Integer; Ok:Boolean; BEGIN Ok := True; i := 1; WHILE (i <= N) AND Ok DO BEGIN Ok := Visitados[i] AND (Valores[i] = 0); i := i + 1 END; TodosVisitadosYNeutrales := Ok END; (*TodosVisitadosYNeutrales *) FUNCTION Equilibrado(GDV: tGrafo; Valores: tValores): Boolean; VAR Visitados : tVisitados; i : tVertice; BEGIN recalculaValores(Valores, GDV); FOR i := 1 TO N DO Visitados[i] := False; Visitar2(1, GDV, Visitados); Equilibrado := TodosVisitadosYNeutrales(Visitados, Valores) END; (* Equilibrado *) Universidad Politécnica de Madrid – E.U. Informática Página 3 3º) (3 Puntos) Dado un vector que contiene N números enteros, se pide: siguiendo el esquema Divide y Vencerás, desarrollar en lenguaje Pascal un algoritmo que determine la posición dentro del vector, si existe, de dos elementos consecutivos que cumplan las siguientes condiciones: ambos poseen el mismo signo y además su suma -en valor absolutoes máxima. Si no existen, devolverá el valor -1. Ejemplo: 1 -2 20 -20 2 3 -3 -10 2 3 4 1 2 3 4 5 6 7 8 9 10 11 Deberá devolver 7, que corresponde a los valores -3 y -10 del vector. CONST N = ???; TYPE tVector = ARRAY [1..N] OF Integer; FUNCTION SumaMaxima(VAR Vector: tVector; Iz, De: Integer; VAR suma: Integer): Integer; VAR ind1, ind2, sum1, sum2, Medio, maximo: Integer; BEGIN IF De = Iz (* caso base *) THEN BEGIN SumaMaxima := -1; suma := -1; END ELSE BEGIN Medio := (De + Iz) DIV 2; ind1 := SumaMaxima(Vector, Iz, Medio, sum1); ind2 := SumaMaxima(Vector, Medio + 1, De, sum2); (* Combinación resultados *) IF sum1 > sum2 THEN BEGIN suma := sum1; maximo := ind1; END ELSE BEGIN suma := sum2; maximo := ind2 END; IF ((Vector[Medio] >= 0) AND (Vector[Medio + 1] >= 0)) OR ((Vector[Medio] < 0) AND (Vector[Medio + 1] < 0)) THEN IF Abs(Vector[Medio] + Vector[Medio + 1]) > suma THEN BEGIN suma := Abs(Vector[Medio] + Vector[Medio + 1]); maximo := Medio END; SumaMaxima := maximo END END; (* SumaMaxima *) (* secuencia *) PROCEDURE buscarSumaMaxima(Vector: tVector; Iz, De: Integer); VAR indMax, sum: Integer; BEGIN indMax := SumaMaxima(Vector, Iz, De, sum); WriteLn; IF indMax = -1 THEN WriteLn('No hay ninguna secuencia') ELSE WriteLn('La secuencia está en la posición: ', indMax); END; (* buscarSumaMaxima *) Universidad Politécnica de Madrid – E.U. Informática Página 4