Dpto. O.E.I. – U.P.M. ALGORÍTMICA 03/FEB/10 1º) (3’5 Puntos) Se dispone de una matriz con N filas y M columnas inicializada aleatoriamente con ceros y unos. La última columna sólo contiene unos. También se dispone de una ficha que sólo puede desplazarse a las casillas que contengan un uno según los movimientos que se muestran en la siguiente figura: ⊗ Se pide: implementar un algoritmo en Pascal que partiendo de una de una determinada casilla, y pasando exclusivamente por celdas que contengan unos, determine si es posible llegar a todas las celdas de la última columna. CONST N = …; M = …; Movimientos = 3; TYPE tTablero = ARRAY[1 .. N, T1 .. M] OF 0 .. 1; tDesplazamiento = ARRAY [1 .. Movimientos] OF -1 .. 1; tAlcanzado = ARRAY [1 .. N] OF Boolean; VAR Tablero : tTablero; DesplazamientoFila: tDesplazamiento; Alcanzado: tAlcanzado; Solucion: Boolean; I: Integer; FUNCTION Aceptable(Tablero: tTablero; Fila, Columna: Integer): Boolean; BEGIN IF (Fila >= 1) AND (Fila <= N) THEN Aceptable := (Tablero[Fila, Columna] = 1) ELSE Aceptable := False END; FUNCTION EsSolucion(Alcanzado: tAlcanzado): Boolean; VAR Ok: Boolean; I: Integer; BEGIN Ok := True; I := 1; WHILE (I <= N) AND Ok DO BEGIN Ok := Alcanzado[I]; I := I + 1 END; EsSolucion := Ok END; PROCEDURE Ensayar(VAR Tablero: tTablero; Fila, Columna: Integer; VAR Alcanzado: tAlcanzado; DesplazamintoFila: tDesplazamiento; VAR Solucion: Boolean); VAR Posibilidad, NF, NC: Integer; BEGIN Posibilidad := 0; REPEAT Posibilidad := Posibilidad + 1; NF := Fila + DesplazamintoFila[Posibilidad]; NC := Columna + 1; IF Aceptable(Tablero, NF, NC) THEN IF NC = M THEN BEGIN Alcanzado[NF] := true; IF EsSolucion(Alcanzado) THEN Solucion := True END ELSE Ensayar(Tablero, NF, NC, Alcanzado, DesplazamintoFila, Solucion); UNTIL (Posibilidad = Movimientos) OR Solucion END; BEGIN … DesplazamientoFila[1] := -1; DesplazamientoFila[2] := 0; DesplazamientoFila[3] := +1; FOR I:=1 TO N DO Alcanzado[I] := False; Solucion := False; Ensayar(Tablero, 2, 1, Alcanzado, DesplazamientoFila, Solucion); IF Solucion THEN Writeln('SÍ EXISTE') ELSE Writeln('NO EXISTE SOLUCIÓN') END. Universidad Politécnica de Madrid – E.U. Informática Página 1 2º) (3’5 Puntos) Sea G un Grafo Dirigido representado por su matriz de adyacencia. Se dice que un camino de G <V0, V1, V2, …, Vk> es creciente si se cumple que V0 < V1, V1 < V2, …, y Vk-1 < Vk Se pide: desarrollar un algoritmo en Pascal que determine cual es el camino creciente de mayor longitud entre dos vértices dados (el algoritmo contemplará la posibilidad de que no exista ningún camino creciente entre dichos vértices) CONST NMax = 25; (* Número máximo de vértices *) TYPE tMatrizAdy = ARRAY [1..NMax, 1..NMax] OF Boolean; (* Matriz de Adyacencia *) tVisitados = ARRAY [1..NMax] OF Boolean; VAR GD: tMatrizAdy; v, N, numVertMaximo: Integer; Visitados, VisitadosOpt: tVisitados; (* N: Número real de vértices *) (* Algoritmo de selección óptima *) PROCEDURE CaminoCreciente(VAR GD: tMatrizAdy; (* por ref. para ahorrar memoria *) vActual, vDestino, numVertActual: Integer; VAR numVertMaximo: Integer; VAR Visitados, VisitadosOpt: tVisitados); VAR v: Integer; BEGIN (* vActual < candidatos_aceptables < vDestino *) FOR v := (vActual + 1) TO vDestino DO IF GD[vActual, v] (* aceptable: existe el arco *) THEN BEGIN (* anotar *) numVertActual := numVertActual + 1; Visitados[v] := True; IF v = vDestino (* es solución *) THEN BEGIN IF numVertActual > numVertMaximo THEN BEGIN numVertMaximo := numVertActual; VisitadosOpt := Visitados; END END ELSE CaminoCreciente(GD, v, vDestino, numVertActual, numVertMaximo, Visitados, VisitadosOpt); (* desanotar *) numVertActual := numVertActual - 1; Visitados[v] := False; END END; (* CaminoCreciente *) PROCEDURE Escribir_Camino(Visitados: tVisitados; Origen, Destino: Integer); BEGIN FOR v := Origen TO Destino DO IF Visitados[v] THEN Write(v, ', ') END; (* Escribir_Camino *) BEGIN CargarMatriz(GD); (* Inicializamos el vector de Visitados *) FOR v := 1 TO N DO Visitados[v] := False; (* Llamada al algoritmo de selección óptima: p.ej. origen=1, destino=N *) numVertMaximo := 1; Visitados[1] := True; CaminoCreciente(GD, 1, N, 1, numVertMaximo, Visitados, VisitadosOpt); IF numVertMaximo = 1 (* No se ha encontrado ningún camino *) THEN WriteLn('No hay camino') ELSE BEGIN Escribir_Camino(VisitadosOpt, 1, N); WriteLn(' (', numVertMaximo, ' vértices)') END END. Universidad Politécnica de Madrid – E.U. Informática Página 2 3º) (3 Puntos) Sea G un Grafo Dirigido Valorado. Un vértice w es alcanzable desde v si existe camino en G de v a w. Adicionalmente, se define la accesibilidad de un vértice v como el número de vértices alcanzables desde v. Dada la matriz CM que se obtiene tras la aplicación del algoritmo de Floyd sobre G, se pide: siguiendo el esquema Divide y Vencerás, implementar un algoritmo que determine el vértice (o conjunto de vértices) de G con mayor accesibilidad. CONST NMax = 25; (* Número máximo de vértices *) FichGrafo = 'gdv.txt'; Infinito = MaxInt; TYPE tMatrizCoste = ARRAY [1..NMax, 1..NMax] OF Integer; tVisitados = ARRAY [1..NMax] OF Boolean; VAR CM, GDV: tMatrizCoste; v, N, numVertMaximo: Integer; Visitados: tVisitados; (* N: Número real de vértices *) (* Calcula la accesibilidad del vértice ‘Fila’ *) FUNCTION DyV_Accesibilidad(CM: tMatrizCoste; Fila, Iz, De: Integer): Integer; VAR medio, v, acce1, acce2: Integer; BEGIN IF Iz = De (* caso base *) THEN IF CM[Fila, Iz] = Infinito THEN DyV_Accesibilidad := 0 ELSE DyV_Accesibilidad := 1 ELSE BEGIN medio := (Iz + De) DIV 2; acce1 := DyV_Accesibilidad(CM, Fila, Iz, medio); acce2 := DyV_Accesibilidad(CM, Fila, medio + 1, De); DyV_Accesibilidad := acce1 + acce2; (* suma de los vértices accesibles *) END END; (* DyV_Accesibilidad *) PROCEDURE DyV_MayorAccesibilidad(CM: tMatrizCoste; Inf, Sup: Integer; VAR Vertices: tVisitados; VAR accesibilidad: Integer); VAR Vert1, Vert2: tVisitados; medio, v, acce1, acce2: Integer; BEGIN IF Inf = Sup (* caso base *) THEN BEGIN accesibilidad := DyV_Accesibilidad(CM, Inf, 1, N); FOR v := 1 TO N DO Vertices[v] := False; Vertices[Inf] := True; END ELSE BEGIN medio := (Inf + Sup) DIV 2; DyV_MayorAccesibilidad(CM, Inf, medio, Vert1, acce1); DyV_MayorAccesibilidad(CM, medio + 1, Sup, Vert2, acce2); IF acce1 > acce2 THEN BEGIN Vertices := Vert1; accesibilidad := acce1; END ELSE IF acce2 > acce1 THEN BEGIN Vertices := Vert2; accesibilidad := acce2; END ELSE BEGIN (* misma accesibilidad *) Vertices := Vert1; FOR v := medio + 1 TO Sup DO Vertices[v] := Vert2[v]; accesibilidad := acce1 END END END; (* DyV_MayorAccesibilidad *) Universidad Politécnica de Madrid – E.U. Informática Página 3 PROCEDURE MayorAccesibilidad(CM: tMatrizCoste); VAR Vertices: tVisitados; accesibilidad, v: Integer; BEGIN DyV_MayorAccesibilidad(CM, 1, N, Vertices, accesibilidad); WriteLn('Máxima accesibilidad: ', accesibilidad); Write('Vértices: '); FOR v := 1 TO N DO IF Vertices[v] THEN Write(v, ' ') END; BEGIN (* programa principal *) CargarMatriz(GDV); Floyd(GDV, CM); MayorAccesibilidad(CM); END. Universidad Politécnica de Madrid – E.U. Informática Página 4