Dpto. O.E.I. – U.P.M. ALGORÍTMICA 07/FEB/07 1º) (3'5 Puntos) Sea G un Grafo Dirigido Valorado con N vértices representado por su matriz de costes. Se pide: Desarrollar un algoritmo en Pascal que obtenga, si es que existe, la cadena con menor coste posible que pase una única vez por cada uno de los vértices del grafo. (* En el vector de visitados se almacenará además el orden en que se visitan los vértices *) TYPE tVisitados = ARRAY [1..N] OF Integer; (* Cadena de menor coste que pasa por todos los vértices una sola vez. Esquema de selección óptima *) PROCEDURE CadeMin (GDV: tMatrizCoste; vActual, costeActual, pos: Integer; VAR costeMin: Integer; VAR Visitados, Solucion: tVisitados); VAR i, w, arcoMenor: Integer; BEGIN FOR w := 1 TO N DO IF (Visitados[w] = 0) AND (GDV[vActual, w] <> Infinito OR GDV[w, vActual] <> Infinito) THEN BEGIN IF GDV[vActual, w] < GDV[w, vActual] (* arco de menor coste, es cadena *) THEN arcoMenor := GDV[vActual, w] ELSE arcoMenor := GDV[w, vActual]; Visitados[w] := pos; (* orden en el que se visitan los vértices *) IF costeActual + arcoMenor < costeMin THEN IF pos = N (* se han visitado todos los vértices *) THEN BEGIN (* nueva solución óptima *) costeMin := costeActual + arcoMenor; FOR i := 1 TO N DO Solucion[i] := Visitados[i]; END ELSE CadeMin(GDV, w, costeActual+arcoMenor, pos+1, costeMin, Visitados, Solucion); Visitados[w] := 0 END END; (* CadeMin *) (* PROGRAMA PRINCIPAL *) BEGIN costeMin := Infinito; FOR i := 1 TO N DO Visitados[i] := 0; (* el origen de la solución puede ser cualquier vértice *) FOR vInicio := 1 TO N DO BEGIN Visitados[vInicio] := 1; CadeMin(GDV, vInicio, 0, 2, costeMin, Visitados, Solucion) Visitados[vInicio] := 0; END; (* mostrar resultados *) IF costeMin = Infinito THEN writeLn('No existe solución') ELSE BEGIN writeLn('Coste de la cadena mínima: ', costeMin); writeLn('Los vértices se deben visitar en el siguiente orden:'); FOR i := 1 TO N DO writeLn('Vértice ', i:2, ': orden', Solucion[i]:2); END END. 2º) (3,5 Puntos) Se dispone de una matriz de NxN enteros. Se desea saber si en dicha matriz existe un conjunto de N coordenadas (X, Y) que cumplan las siguientes condiciones: El contenido de la matriz en cada una de las coordenadas (X, Y) coincide con el valor de Y, es decir, M[X, Y] = Y No pueden aparecer 2 ó más coordenadas con el mismo valor de X. Se pide: Desarrollar un algoritmo en Pascal que determine si existe un conjunto de N coordenadas que cumplan las condiciones anteriores. 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 4 5 6 1 2 1 2 1 2 3 4 5 6 7 3 2 2 1 6 7 3 8 4 5 5 4 5 1 2 5 5 5 1 7 7 7 7 2 6 8 6 2 6 7 5 6 7 1 2 7 8 8 5 7 8 2 1 5 5 8 8 7 Dado el tablero de la izquierda, un posible conjunto de N coordenadas que cumple las condiciones establecidas sería el formado por: { C = (1,1), (3,2), (7,3), (4,4), (2,5), (5,6), (8,7), (6,8) FUNCTION Buscar_Coordenadas(Tablero: tTablero): Boolean; VAR X, Y: Integer; Encontrado: Boolean; BEGIN Encontrado := True; X := 1; WHILE (X <= N) AND Encontrado DO BEGIN Y := 1; Encontrado := False; WHILE (Y <= N) AND (Not Encontrado) DO BEGIN IF (Tablero[X, Y] = Y) THEN Encontrado := True; Y := Y + 1 END; X := X + 1 END; Buscar_Coordenadas := Encontrado END; (* PROGRAMA PRINCIPAL *) Solucion := Buscar_Coordenadas(Tablero); } Dpto. O.E.I. – U.P.M. ALGORÍTMICA 07/FEB/07 3º) (3 Puntos) Sea G un Grafo Árbol Dirigido no valorado representado por listas de adyacencia, y dado Costes que es un vector de enteros que contiene el coste asociado a cada vértice de G. Se define el Coste Ponderado por Descendiente (CPD) del grafo como: CPD = Costes v * numerodedescendientes(v) v V Se pide: Siguiendo el esquema Divide y Vencerás, desarrollar un algoritmo en Pascal que obtenga el Coste Ponderado por Descendiente del Grafo (la raíz es el vértice 1). 1 2 Vector de Costes 3 5 4 6 7 8 1 2 3 4 5 6 7 8 9 10 10 20 20 20 30 30 30 30 CPD = Costes[1]*8 + Costes[3]*5 + Costes[6]*3 = 10*8 + 20*5 +30 *3 = 270 9 FUNCTION CPD(G: tGrafoListasAdy; actual: Integer; Costes: tArray; VAR Hijos: Integer): Integer; VAR CPDs, Descendientes: ARRAY [1..N] OF Integer ; Resultado, Trato: Integer; Aux: tListaAdyacencia; BEGIN IF (G[actual] = NIL) THEN (* caso base *) BEGIN Hijos := 1; Resultado := 0; END ELSE BEGIN (* Inicialización variables locales para recoger los resultados de las llamadas *) FOR Trato := 1 TO N DO BEGIN Descendientes[Trato] := 0; CPDs[Trato] := 0 END; (* División del problema. Hay que generar una llamada por cada hijo *) Aux := G[actual]; WHILE Aux <> NIL DO BEGIN CPDs[Aux^.Nodo] := CPD (G, Aux^.Nodo, Costes, Descendientes[Aux^.Nodo]); Aux := Aux^.Siguiente END; (* Proceso de Mezcla *) Resultado := 0; (* Cuento el número de Hijos *) FOR Trato := 1 TO N DO Resultado := Resultado + Descendientes[Trato]; Hijos := Resultado + 1; (* Hay que contar el nodo actual *) (* coste del vértice actual *) Resultado := Resultado * Costes [actual]; (* sumatorio pedido *) FOR Trato := 1 TO N DO Resultado := Resultado + CPDs[Trato] END; CPD := Resultado END; (* CPD *) BEGIN Hijos := 0; Resultado := CPD(Grafo, 1, Costes, Hijos); writeLn ('El resultado es:', Resultado) END.