Algoritmos de Esquemas en Java: Voraz, Vuelta Atrás, Grafos y Backtracking

Clasificado en Informática

Escrito el en español con un tamaño de 14,96 KB

Esquemas algorítmicos en Java

A continuación se presentan los ejercicios de esquemas algorítmicos implementados en Java, organizados por técnica: algoritmos voraces, vuelta atrás (backtracking) y grafos.

Ejercicio 1: Dar el cambio voraz

public class Esquemas {

// Ejercicio 1: Dar el cambio voraz

public static Map darCambio(int importeDevolver, Map cantidades) {

Map solucion = new HashMap<>();

int importeDevuelto = 0;
boolean devolverMas = true;
while (importeDevuelto < importeDevolver && devolverMas) {

Integer billeteSel = mayor(importeDevolver - importeDevuelto, cantidades);
if (billeteSel != 0) {

int cantBil = (importeDevolver - importeDevuelto) / billeteSel;

int tot = cantidades.get(billeteSel);
if (cantBil > tot) cantBil = tot;
solucion.insertar(billeteSel, cantBil);
importeDevuelto += billeteSel * cantBil;
if (tot - cantBil == 0) cantidades.eliminar(billeteSel);
else cantidades.insertar(billeteSel, tot - cantBil);
} else devolverMas = false; // No se puede devolver

}

if (devolverMas == false) return new HashMap<>();
else return solucion;
}

private static Integer mayor(int importeQueda, Map cant) {
Integer billMax = 0;
Iterator it_bill = cant.getClaves();

while (it_bill.hasNext()) {
Integer bill = it_bill.next();

if (bill > billMax && bill <= importeQueda && cant.get(bill) > 0) {
billMax = bill;
}
}
return billMax;
}

// Ejercicio 2: Dar el cambio vuelta atrás

public static boolean darCambio(int importeDevolver, Map cantidades, Map solucion) {

boolean objetivo = false;
Iterator it_bill = cantidades.getClaves();

while (it_bill.hasNext() && !objetivo) {
int moneda = it_bill.next();

if (cantidades.get(moneda) > 0 && importeDevolver >= moneda) {
cantidades.insertar(moneda, cantidades.get(moneda) - 1);
if (moneda == importeDevolver) {
solucion.insertar(moneda, solucion.get(moneda) + 1);
objetivo = true;
} else {
objetivo = darCambio(importeDevolver - moneda, cantidades, solucion);
if (objetivo)
solucion.insertar(moneda, solucion.get(moneda) + 1);
else {
cantidades.insertar(moneda, cantidades.get(moneda) + 1);
}
}
}
}
return objetivo;
}

Ejercicio 3: Grabar CD voraz

// Ejercicio 3: Grabar CD voraz
public static Lista llenarCDVoraz(int capacidadMaxima, Map espacioProgramas) {

Lista CD = new ListaEnlazada();
int espacioOcupado = 0;
boolean llenarMas = true;

int k = 0;
while (espacioOcupado < capacidadMaxima && llenarMas) {

String prog = mayor(capacidadMaxima - espacioOcupado, espacioProgramas, CD);
if (prog != null) {
k = espacioProgramas.get(prog);
espacioProgramas.eliminar(prog);
CD.insertarPrincipio(prog);
espacioOcupado += k;
} else llenarMas = false;
}

return CD;
}

private static String mayor(int parcial, Map progr, Lista sol) {
String maxProg = null;
int maxEsp = 0;

Iterator it_prog = progr.getClaves();

while (it_prog.hasNext()) {
String prog = it_prog.next();
int esp = progr.get(prog);

if (!sol.contiene(prog) && esp > maxEsp && esp <= parcial) {
maxEsp = esp;
maxProg = prog;
}
}

return maxProg;
}

Ejercicio 4: Grabar CD vuelta atrás

// Ejercicio 4: Grabar CD vuelta atrás
public static boolean llenarCDVueltaAtras(int capacidadCD, Map programas, Lista CD) {

boolean objetivo = false;
Iterator itProgramas = programas.getClaves();

while (itProgramas.hasNext() && !objetivo) {
String program = itProgramas.next();
int capacProgram = programas.get(program);

if (capacProgram > 0 && capacidadCD >= capacProgram) {
programas.eliminar(program);
if (capacProgram == capacidadCD) {
CD.insertarPrincipio(program);
objetivo = true;
} else {
objetivo = llenarCDVueltaAtras(capacidadCD - capacProgram, programas, CD);
if (objetivo)
CD.insertarPrincipio(program);
else {
programas.insertar(program, capacProgram);
}
}
}
}
return objetivo;
}

Ejercicio 5: Llenar mochila voraz

// Ejercicio 5: Llenar mochila

public static Map llenarMochila(int volumenMaximo, Map cantidades, Map volumenes) {

Map S = new HashMap<>();
int volumenOcupado = 0;
boolean llenarMas = true;

int cantObj = 0;
while (volumenOcupado < volumenMaximo && llenarMas) {
String obj = mayor(volumenMaximo - volumenOcupado, cantidades, volumenes);
if (obj != null) {
int vol = volumenes.get(obj);
cantObj = (volumenMaximo - volumenOcupado) / vol;
int tot = cantidades.get(obj);
if (cantObj > tot) cantObj = tot;

S.insertar(obj, cantObj);
if (tot - cantObj == 0) cantidades.eliminar(obj);
else cantidades.insertar(obj, tot - cantObj);

volumenOcupado += vol * cantObj;
} else llenarMas = false; // No se puede llenar más, devolvemos la mochila
}

return S;
}

private static String mayor(int parcial, Map c, Map v) {
String max = null;
int maxV = 0;

Iterator obj = v.getClaves();

while (obj.hasNext()) {
String m = obj.next();
int vol = v.get(m);
int cant = c.get(m);

if (cant > 0 && vol > maxV && vol <= parcial) {
maxV = vol;
max = m;
}
}

return max;
}

Ejercicio 6: Llenar mochila con restricción de volumen y peso

// Ejercicio 6: Llenar mochila, restricción de volumen y peso

public static Map llenarMochila(int volumenMaximo, int pesoMaximo, Map cantidades, Map volumenes, Map pesos) {

Map solucion = new HashMap<>();

int volumenOcupado = 0;
int pesoOcupado = 0;
boolean llenarMas = true;

// Mientras no se haya cumplido el objetivo con los objetos disponibles
while (volumenOcupado < volumenMaximo && llenarMas) {
// buscar un objeto que quepa
String obj = mayor(volumenMaximo - volumenOcupado, pesoMaximo - pesoOcupado, volumenes, cantidades, pesos);
if (obj != null) {
int vol = volumenes.get(obj);
int pes = pesos.get(obj);

int cantObj = (volumenMaximo - volumenOcupado) / vol; // ¿Cuántos objetos según volumen?
int s = (pesoMaximo - pesoOcupado) / pes; // ¿Cuántos objetos según peso?

if (cantObj > s) cantObj = s; // Me quedo con la cantidad más pequeña

int tot = cantidades.get(obj); // ¿Cuántos objetos tengo realmente?
if (cantObj > tot) cantObj = tot;

solucion.insertar(obj, cantObj);

if (tot - cantObj == 0) cantidades.eliminar(obj);
else cantidades.insertar(obj, tot - cantObj);

volumenOcupado += vol * cantObj;
pesoOcupado += pes * cantObj;
} else llenarMas = false; // No se puede llenar más, devolvemos la mochila
}

return solucion;
}

private static String mayor(int parcialVolumen, int parcialPeso, Map v, Map c, Map p) {
String max = null;
int maxV = 0;

Iterator obj = v.getClaves();

while (obj.hasNext()) {
String m = obj.next();
int vol = v.get(m);
int pes = p.get(m);

if (c.get(m) > 0 && vol > maxV && vol <= parcialVolumen && pes <= parcialPeso) {
maxV = vol;
max = m;
}
}

return max;
}

// El grafo debe estar bien construido, si no es posible que queden ciudades sin visitar

Ejercicio 7: Viajante (ciudades)

public static Grafo viajante(Grafo g, Vertice v) {
Vertice nodoActual = v;
Lista<Vertice> porVisitar = new ListaEnlazada<>();
Grafo solucion = new ListaAdyacencia<>();

Iterator<Vertice> it_v = g.vertices();

while (it_v.hasNext()) {
Vertice vert = it_v.next();
porVisitar.insertarPrincipio(vert);
}

porVisitar.suprimir(nodoActual);

boolean continuar = true;

while (!porVisitar.esVacio() && continuar) {
Arco u = minimo(g.arcos(), nodoActual, porVisitar);
if (u != null) {
porVisitar.suprimir(u.getDestino());
solucion.insertarArco(u);
nodoActual = u.getDestino();
} else continuar = false;
}
return solucion;
}

private static Arco minimo(Iterator<Arco> arc, Vertice v, Lista<Vertice> iPorVisitar) {
int dist_v_min = 0;
int min = Integer.MAX_VALUE;
Arco arco_min = null;
while (arc.hasNext()) {
Arco a1 = arc.next();
Vertice w = a1.getDestino();
if (a1.getOrigen().equals(v) && iPorVisitar.contiene(w)) {
dist_v_min = a1.getEtiqueta();
if (dist_v_min < min) {
arco_min = a1;
min = dist_v_min;
}
}
}
return arco_min;
}

Ejercicio 8: Algoritmo de Prim

public static Grafo prim(Grafo g, Vertice v) {
Lista<Vertice> porVisitar = new ListaEnlazada<>();
Lista<Vertice> visitados = new ListaEnlazada<>();
Grafo solucion = new ListaAdyacencia<>();

Iterator<Vertice> it_v = g.vertices();

while (it_v.hasNext()) {
Vertice vert = it_v.next();
porVisitar.insertarPrincipio(vert);
}

porVisitar.suprimir(v);
visitados.insertarPrincipio(v);

while (!porVisitar.esVacio()) {
Arco u = minimo(g.arcos(), porVisitar, visitados);
Vertice w = u.getDestino();
porVisitar.suprimir(w);
visitados.insertarPrincipio(w);
solucion.insertarArco(u);
}
return solucion;
}

private static Arco minimo(Iterator<Arco> arc, Lista<Vertice> iPorVisitar, Lista<Vertice> iVisitados) {
int dist_v_min = 0;
int min = Integer.MAX_VALUE;
Arco arco_min = null;

while (arc.hasNext()) {
Arco a1 = arc.next();
Vertice w = a1.getDestino();
Vertice v = a1.getOrigen();

if (iPorVisitar.contiene(w) && iVisitados.contiene(v)) {
dist_v_min = a1.getEtiqueta();
if (dist_v_min < min) {
arco_min = a1;
min = dist_v_min;
}
}
}
return arco_min;
}

Ejercicio 9: 8 reinas

// Ejercicio 9: 8 reinas

private static boolean buenSitio(int j, int[] tabl) {
// ¿Es amenaza colocar la reina j en A[j], con las anteriores?
int i;
for (i = 0; i < j; ++i) {
if (tabl[i] == tabl[j]) return false;
if (Math.abs(i - j) == Math.abs(tabl[i] - tabl[j])) return false;
}
return true;
}

public static boolean colocarReinas(int reina, int[] tablero) {
boolean objetivo = false;
int columna = 0;

// Mientras no se hayan mirado todas las posibilidades o alcanzado el objetivo
while (columna < 8 && !objetivo) {
// Colocar la reina j en la columna
tablero[reina] = columna;
if (buenSitio(reina, tablero)) {
// Si he colocado todas las reinas
if (reina == 7) {
objetivo = true;
} else {
// Hacer el siguiente paso recursivamente (colocar la siguiente reina)
if (colocarReinas(reina + 1, tablero)) {
objetivo = true;
} else {
tablero[reina] = -1; // vuelta atrás
}
}
}
columna++;
}

return objetivo;
}

Ejercicio 10: Laberinto

// Ejercicio 10: Laberinto

public static boolean ensayar(char[][] laberinto, int posicionX, int posicionY) {

int n = laberinto.length; // Tamaño del laberinto n x n
boolean toret;
// ¿Estamos dentro del laberinto?
if ((posicionX < 0) || (posicionX > n - 1) || (posicionY < 0) || (posicionY > n - 1))
toret = false;
else {
// No se puede pasar por encima de los obstáculos
if (laberinto[posicionX][posicionY] != ' ') {
toret = false;
} else {
// Marca como parte del camino
laberinto[posicionX][posicionY] = 'C';

if ((posicionX == n - 1) && (posicionY == n - 1)) {
toret = true; // Se ha encontrado la solución
} else {
// En principio, hay solución
toret = true;

// Hay que desplazarse en vertical u horizontal por las otras casillas
if (!ensayar(laberinto, posicionX + 1, posicionY))
if (!ensayar(laberinto, posicionX, posicionY + 1))
if (!ensayar(laberinto, posicionX - 1, posicionY))
if (!ensayar(laberinto, posicionX, posicionY - 1)) {
laberinto[posicionX][posicionY] = 'I';
toret = false;
}
}
}
}

return toret;
}

Ejercicio 11: Subconjuntos

// Ejercicio 11: subconjunto
public static boolean subconjuntos(int[] valores, int[] solucion, int suma, int i) {
boolean objetivo = false;
while (i < valores.length && !objetivo) {
int candidato = valores[i];
if (candidato <= suma) {
solucion[i] = 1;
if (candidato == suma) {
solucion[i] = 1;
objetivo = true;
} else {
objetivo = subconjuntos(valores, solucion, suma - candidato, i + 1);
if (!objetivo)
solucion[i] = 0; // vuelta atrás
}
}
i++;
}
return objetivo;
}

Ejercicio 12: k-ésimo menor elemento

// Ejercicio 12: k-ésimo menor elemento

// Selecciona un elemento pivote; entre dos elementos diferentes devuelve el elemento mayor
private static int buscaPivote(int i, int j, int[] array) {
int primer = array[i];
int k = i + 1;

while (k <= j) {
if (array[k] > primer)
return k;
else if (array[k] < primer)
return i;
else k++;
}
// Si llega al final del array y todos los elementos son iguales
return -1;
}

// Divide el array en menores que pivote, y mayores o iguales a pivote.
// Devuelve la posición del primer elemento de los mayores.
private static int particion(int i, int j, int pivote, int[] array) {
int derecha = i;
int izquierda = j - 1;
while (derecha <= izquierda) {
intercambiar(derecha, izquierda, array);

while (array[derecha] < pivote)
derecha++;
while (array[izquierda] >= pivote)
izquierda--;
}
return derecha;
}

// Intercambiar dos elementos en el array
private static void intercambiar(int i, int j, int[] array) {
int aux = array[i];
array[i] = array[j];
array[j] = aux;
}

public static int SeleccionRapida(int[] array, int k_menor, int i, int j) {
int indicePivote = buscaPivote(i, j, array);
if (indicePivote != -1) {
int pivote = array[indicePivote];
intercambiar(indicePivote, j, array); // pivote para la última posición
int pos = particion(i, j, pivote, array);
if (pos + 1 == k_menor) return pivote; // encontrado el elemento k_menor
else if (pos >= k_menor)
return SeleccionRapida(array, k_menor, i, pos - 1);
else return SeleccionRapida(array, k_menor, pos, j);
} else return indicePivote;
}

Entradas relacionadas: