Hola a todos, hoy os dejo una serie de ejercicios propuestos y resueltos Java de backtraking.
Todos los ejercicios que proponemos están resueltos en este mismo post, intenta hacerlo por ti mismo y si te quedas atascado puedes mirar la solución. Recuerda, que no tiene por que estar igual tu solución con la del post, el objetivo es que aprendas no que me copies la solución.
Te recomiendo que uses mensajes de trazas, donde te sean necesarios. Si tienes problemas también puedes usar el depurador.
Aquí tienes todos los posts relacionados con Java:
1) Obtener todas las combinaciones de sumar un numero en concreto.
4 = 1 + 1 + 1 + 1
4 = 2 + 2
…
Spoiler Inside | SelectShow> |
---|---|
import java.util.ArrayList; public class Ejercicio_recursividad_DDR_20 { public static void main(String[] args) { int n = 5; ArrayList<Integer> numeros = new ArrayList<>(); combinacionesSuma(n, numeros, 0); } public static void combinacionesSuma(int numero, ArrayList<Integer> numeros, int suma) { //Caso base if (suma == numero) { //Muestro los numeros System.out.println(numeros); } else { for (int i = 1; i <= numero; i++) { suma += i; //Si la suma es mayor que el numero no hacemos la recursividad if (suma <= numero) { //añado el numero numeros.add(i); combinacionesSuma(numero, numeros, suma); //elimino el numero numeros.remove(numeros.indexOf(i)); } //deshago la suma suma -= i; } } } } |
2) Dado un valor y 3 dados, queremos sacar todas las combinaciones que superen a ese valor dado. Por ejemplo:
Si el valor es 15, las combinaciones pueden ser:
6 6 6
6 5 6
5 5 5
5 4 6
…
Spoiler Inside | SelectShow> |
---|---|
public class Ejercicio_recursividad_DDR_23 { public static void main(String[] args) { int[] dados = {1, 1, 1}; int valorSuperar = 15; tiradas(dados, valorSuperar, 0, 0); } public static void tiradas(int[] dados, int valorSuperar, int suma, int tirada) { //Si la tirada es el numero de dados y la suma es mayor que el valor a superar //muestro la solucion if (tirada == dados.length && suma >= valorSuperar) { for (int i = 0; i < dados.length; i++) { if (i == dados.length-1) { System.out.print(dados[i] + "="); } else { System.out.print(dados[i] + "+"); } } System.out.println(suma); } else if (tirada != dados.length) { //Evita problemas por si la tirada es mayor o igual que 3 for (int i = 1; i <= 6; i++) { dados[tirada] = i; //le doy valor al dado suma += i; //sumo tiradas(dados, valorSuperar, suma, tirada + 1); suma -= i; // deshago la suma } } } } |
3) Queremos meter elementos en una mochila con un peso máximo, estos elementos tienen un peso y un beneficio.
Obtener la mejor combinación que mas beneficio nos dé y que no sobrepase el peso de la mochila.
Spoiler Inside | SelectShow> |
---|---|
— Elemento public class Elemento { private int peso; private int beneficio; public Elemento(int peso, int beneficio) { this.peso = peso; this.beneficio = beneficio; } public int getPeso() { return peso; } public void setPeso(int peso) { this.peso = peso; } public int getBeneficio() { return beneficio; } public void setBeneficio(int beneficio) { this.beneficio = beneficio; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final Elemento other = (Elemento) obj; if (this.peso != other.peso) { return false; } if (this.beneficio != other.beneficio) { return false; } return true; } @Override public String toString(){ return "Peso:"+peso+","+" beneficio:"+beneficio; } } — Mochila public class Mochila { private int pesoMaximo; private Elemento[] elementos; private int peso; private int beneficio; public Mochila(int pesoMaximo, int numElementos) { this.pesoMaximo = pesoMaximo; this.elementos = new Elemento[numElementos]; this.beneficio = 0; this.peso = 0; } public Elemento[] getElementos() { return elementos; } public int getPeso() { return peso; } public void setPeso(int peso) { this.peso = peso; } public int getBeneficio() { return beneficio; } public void setBeneficio(int beneficio) { this.beneficio = beneficio; } public int getPesoMaximo() { return pesoMaximo; } public void setPesoMaximo(int pesoMaximo) { this.pesoMaximo = pesoMaximo; } /** * Añade un elemento a la mochila * @param e */ public void aniadirElemento(Elemento e) { for (int i = 0; i < this.elementos.length; i++) { if (this.elementos[i] == null) { this.elementos[i] = e; //lo añade this.beneficio+=e.getBeneficio(); // aumenta el beneficio this.peso+=e.getPeso(); // Aumenta el piso break; } } } /** * Vaciamos la mochila */ public void clear() { this.peso=0; this.beneficio=0; for (int i = 0; i < this.elementos.length; i++) { this.elementos[i] = null; } } /** * Elimina elemento dado * @param e */ public void eliminarElemento(Elemento e) { for (int i = 0; i < this.elementos.length; i++) { if (this.elementos[i].equals(e)) { this.elementos[i] = null; //el elemento fuera this.peso-=e.getPeso(); //Reduce el peso this.beneficio-=e.getBeneficio(); // reduce el beneficio break; } } } /** * Indica si existe un elemento * @param e * @return */ public boolean existeElemento(Elemento e) { for (int i = 0; i < this.elementos.length; i++) { if (this.elementos[i] != null && this.elementos[i].equals(e)) { return true; } } return false; } /** * Muestra la mochila * @return */ public String toString() { String cadena=""; for (int i = 0; i < this.elementos.length; i++) { if (this.elementos[i] != null) { cadena+=elementos[i]+"\n"; } } cadena+="Peso: " + getPeso()+"\n"; cadena+="Beneficio: " + getBeneficio()+"\n"; return cadena; } } — Main public class Mochila { private int pesoMaximo; private Elemento[] elementos; private int peso; private int beneficio; public Mochila(int pesoMaximo, int numElementos) { this.pesoMaximo = pesoMaximo; this.elementos = new Elemento[numElementos]; this.beneficio = 0; this.peso = 0; } public Elemento[] getElementos() { return elementos; } public int getPeso() { return peso; } public void setPeso(int peso) { this.peso = peso; } public int getBeneficio() { return beneficio; } public void setBeneficio(int beneficio) { this.beneficio = beneficio; } public int getPesoMaximo() { return pesoMaximo; } public void setPesoMaximo(int pesoMaximo) { this.pesoMaximo = pesoMaximo; } /** * Añade un elemento a la mochila * @param e */ public void aniadirElemento(Elemento e) { for (int i = 0; i < this.elementos.length; i++) { if (this.elementos[i] == null) { this.elementos[i] = e; //lo añade this.beneficio+=e.getBeneficio(); // aumenta el beneficio this.peso+=e.getPeso(); // Aumenta el piso break; } } } /** * Vaciamos la mochila */ public void clear() { this.peso=0; this.beneficio=0; for (int i = 0; i < this.elementos.length; i++) { this.elementos[i] = null; } } /** * Elimina elemento dado * @param e */ public void eliminarElemento(Elemento e) { for (int i = 0; i < this.elementos.length; i++) { if (this.elementos[i].equals(e)) { this.elementos[i] = null; //el elemento fuera this.peso-=e.getPeso(); //Reduce el peso this.beneficio-=e.getBeneficio(); // reduce el beneficio break; } } } /** * Indica si existe un elemento * @param e * @return */ public boolean existeElemento(Elemento e) { for (int i = 0; i < this.elementos.length; i++) { if (this.elementos[i] != null && this.elementos[i].equals(e)) { return true; } } return false; } /** * Muestra la mochila * @return */ public String toString() { String cadena=""; for (int i = 0; i < this.elementos.length; i++) { if (this.elementos[i] != null) { cadena+=elementos[i]+"\n"; } } cadena+="Peso: " + getPeso()+"\n"; cadena+="Beneficio: " + getBeneficio()+"\n"; return cadena; } } |
4) Crea un tablero que represente un laberinto, este tendrá una casilla de inicio y otra de fin.
Hay que mostrar todos los posibles caminos del inicio al fin. Teniendo en cuenta que en las casillas pueden haber paredes.
Spoiler Inside | SelectShow> |
---|---|
— Casilla public class Casilla { private int posX; private int posY; private boolean visitado; private boolean fin; private boolean paso[]; //0 = arriba, 1 =derecha, 2= abajo, 3=izquierda public Casilla(int posX, int posY, boolean[] paso, boolean fin) { this.posX = posX; this.posY = posY; this.visitado = false; this.paso = paso; this.fin = fin; } public boolean isFin() { return fin; } public void setFin(boolean fin) { this.fin = fin; } public boolean arribaDisponible() { return paso[0]; } public boolean derechaDisponible() { return paso[1]; } public boolean abajoDisponible() { return paso[2]; } public boolean izquierdaDisponible() { return paso[3]; } public int getPosX() { return posX; } public void setPosX(int posX) { this.posX = posX; } public int getPosY() { return posY; } public void setPosY(int posY) { this.posY = posY; } public boolean isVisitado() { return visitado; } public void setVisitado(boolean visitado) { this.visitado = visitado; } @Override public String toString() { return "X=" + posX + ", Y=" + posY; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final Casilla other = (Casilla) obj; if (this.posX != other.posX) { return false; } if (this.posY != other.posY) { return false; } return true; } } — Tablero import java.util.ArrayList; public class Laberinto { private Casilla[][] tablero; private ArrayList<ArrayList<Casilla>> caminos; public Laberinto(Casilla[][] tablero) { this.tablero = tablero; caminos = new ArrayList<>(); } /** * Indica si se puede mover hacia arriba * @param casillaActual * @param casillaDestino * @return */ public boolean arribaDisponible(Casilla casillaActual, Casilla casillaDestino) { if (casillaDestino != null && !casillaDestino.isVisitado()) { return casillaActual.arribaDisponible(); } return false; } /** * Indica si se puede mover hacia la derecha * @param casillaActual * @param casillaDestino * @return */ public boolean derechaDisponible(Casilla casillaActual, Casilla casillaDestino) { if (casillaDestino != null && !casillaDestino.isVisitado()) { return casillaActual.derechaDisponible(); } return false; } /** * Indica si se puede mover hacia abajo * @param casillaActual * @param casillaDestino * @return */ public boolean abajoDisponible(Casilla casillaActual, Casilla casillaDestino) { if (casillaDestino != null && !casillaDestino.isVisitado()) { return casillaActual.abajoDisponible(); } return false; } /** * Indica si se puede mover hacia la izquierda * @param casillaActual * @param casillaDestino * @return */ public boolean izquierdaDisponible(Casilla casillaActual, Casilla casillaDestino) { if (casillaDestino != null && !casillaDestino.isVisitado()) { return casillaActual.izquierdaDisponible(); } return false; } /** * Coge la casilla indicada * @param x * @param y * @return */ public Casilla getCasillaAt(int x, int y) { if (dentroDelLimite(x, y)) { return tablero[x][y]; } return null; } /** * Indica si esta dentro del limite * @param x * @param y * @return */ public boolean dentroDelLimite(int x, int y) { return (x >= 0 && x < tablero.length) && (y >= 0 && y < tablero[0].length); } /** * añade un camino a la solucion * @param camino */ public void añadirCamino(ArrayList<Casilla> camino) { if (camino != null && !camino.isEmpty()) { caminos.add(camino); } } /** * Muestra los caminos */ public void mostrarCaminos() { int i = 1; for (ArrayList<Casilla> camino : caminos) { System.out.println("Camino: " + i); for (Casilla c : camino) { System.out.println(c); } i++; } } } — Main import java.util.ArrayList; public class Ejercicio_recursividad_DDR_22 { public static void main(String[] args) { //Generacion del tablero Casilla[][] tablero = { { new Casilla(0, 0, new boolean[]{false, true, true, false}, false), new Casilla(0, 1, new boolean[]{false, true, false, true}, false), new Casilla(0, 2, new boolean[]{false, false, true, true}, false), new Casilla(0, 3, new boolean[]{false, false, true, false}, false) }, { new Casilla(1, 0, new boolean[]{true, true, true, false}, false), new Casilla(1, 1, new boolean[]{false, false, false, true}, false), new Casilla(1, 2, new boolean[]{false, true, true, false}, false), new Casilla(1, 3, new boolean[]{true, false, false, true}, false) }, { new Casilla(2, 0, new boolean[]{true, true, true, false}, false), new Casilla(2, 1, new boolean[]{false, true, false, true}, false), new Casilla(2, 2, new boolean[]{true, true, true, true}, false), new Casilla(2, 3, new boolean[]{false, false, false, true}, false) }, { new Casilla(3, 0, new boolean[]{true, true, false, false}, false), new Casilla(3, 1, new boolean[]{false, true, false, true}, false), new Casilla(3, 2, new boolean[]{true, true, false, true}, false), new Casilla(3, 3, new boolean[]{false, false, false, true}, true) } }; //Posible camino que puede haber ArrayList<Casilla> camino = new ArrayList<>(); //Creo el laberinto Laberinto laberinto = new Laberinto(tablero); camino.add(tablero[0][0]); rellenarCaminos(laberinto, tablero[0][0], camino); //Muestro las soluciones laberinto.mostrarCaminos(); } public static void rellenarCaminos(Laberinto laberinto, Casilla casillaActual, ArrayList<Casilla> camino) { //si la casilla donde estoy en la final, acabo if (casillaActual.isFin()) { //añado un clon del camino laberinto.añadirCamino((ArrayList<Casilla>) camino.clone()); } else { //Movimientos disponibles int[][] movimientos = { {-1, 0}, //arriba {0, 1}, // derecha {1, 0}, // abajo {0, -1} // izquierda }; int posXnueva, posYnueva; Casilla aux; //Pruebo los posibles caminos for (int i = 0; i < movimientos.length; i++) { posXnueva = casillaActual.getPosX() + movimientos[i][0]; posYnueva = casillaActual.getPosY() + movimientos[i][1]; aux = laberinto.getCasillaAt(posXnueva, posYnueva); switch (i) { case 0: //arriba if (laberinto.arribaDisponible(casillaActual, aux)) { //la añado al camino camino.add(aux); //la marco como visitada casillaActual.setVisitado(true); rellenarCaminos(laberinto, aux, camino); //la desmarco como visitada casillaActual.setVisitado(false); // la elimino del camino camino.remove(aux); } break; case 1: //derecha if (laberinto.derechaDisponible(casillaActual, aux)) { //la añado al camino camino.add(aux); //la marco como visitada casillaActual.setVisitado(true); rellenarCaminos(laberinto, aux, camino); //la desmarco como visitada casillaActual.setVisitado(false); // la elimino del camino camino.remove(aux); } break; case 2://abajo if (laberinto.abajoDisponible(casillaActual, aux)) { //la añado al camino camino.add(aux); //la marco como visitada casillaActual.setVisitado(true); rellenarCaminos(laberinto, aux, camino); //la desmarco como visitada casillaActual.setVisitado(false); // la elimino del camino camino.remove(aux); } break; case 3: //izquierda if (laberinto.izquierdaDisponible(casillaActual, aux)) { //la añado al camino camino.add(aux); //la marco como visitada casillaActual.setVisitado(true); rellenarCaminos(laberinto, aux, camino); //la desmarco como visitada casillaActual.setVisitado(false); // la elimino del camino camino.remove(aux); } break; } } } } } |
5) Tenemos una diana con i regiones distintas cada una con una puntuación Ri(por ejemplo 4 regiones de valores 10,25,50 y 75puntos), y disponemos de D dardos (por ejemplo 5) para alcanzar una cierta puntuación P (por ejemplo, 100 puntos).
Saca la primera solución posible.
Spoiler Inside | SelectShow> |
---|---|
public class Ejercicio_recursividad_DDR_32 { public static void main(String[] args) { // Zonas donde puedo puntuar int zonas[] = {10, 25, 50, 75}; // numero de dardos que lanzo int dardos = 5; // Regiones con el numero de dardos en cada region int regionesDadas[] = new int[zonas.length]; // puntuacion que se debe llegar int puntuacion = 100; int etapa = 0; int solucion[] = new int[zonas.length]; dardosV1(solucion, zonas, regionesDadas, dardos, etapa, 0, puntuacion); mostrarSolucion(zonas, solucion); } public static boolean dardosV1( int[] solucion, int[] zonas, int[] regionesDadas, int dardos, int etapa, int puntuacionActual, int puntuacionIgualar ) { boolean fin = false; if (dardos == 0 || etapa == zonas.length || calcularPuntuacion(zonas, regionesDadas) == puntuacionIgualar) { if (calcularPuntuacion(zonas, regionesDadas) == puntuacionIgualar) { for (int i = 0; i < zonas.length; i++) { solucion[i] = regionesDadas[i]; } fin = true; } } else { for (int d = 0; d <= dardos && !fin; d++) { int puntuacionZona = zonas[etapa] * d; puntuacionActual += puntuacionZona; if (puntuacionActual <= puntuacionIgualar) { regionesDadas[etapa] = d; fin = dardosV1( solucion, zonas, regionesDadas, dardos - d, etapa + 1, puntuacionActual, puntuacionIgualar ); regionesDadas[etapa] = 0; } } } return fin; } /** * Calcula los puntos de las zonas segun las regiones dadas * * @param zonas * @param regionesDada * @return */ public static int calcularPuntuacion(int[] zonas, int[] regionesDada) { int puntos = 0; // Recorro las regiones donde tengo el numero de dardos for (int i = 0; i < regionesDada.length; i++) { // Sumo los puntos puntos += zonas[i] * regionesDada[i]; } return puntos; } /** * Muestra el resultado segun los dardos usados Por ejemplo: 0 2 1 0 * (regiones) => 25 25 50 * * @param zonas * @param regionesDada */ public static void mostrarSolucion(int[] zonas, int[] regionesDada) { // Recorro las regiones donde tengo el numero de dardos for (int i = 0; i < regionesDada.length; i++) { // Si es distinto de cero if (regionesDada[i] != 0) { // muestro la zona repetida tantas veces como dardos haya for (int j = 0; j < regionesDada[i]; j++) { System.out.print(zonas[i] + " "); } } } System.out.println(""); } } |
6) Tenemos una diana con i regiones distintas cada una con una puntuación Ri(por ejemplo 4 regiones de valores 10,25,50 y 75puntos), y disponemos de D dardos (por ejemplo 5) para alcanzar una cierta puntuación P (por ejemplo, 100 puntos).
Saca todas las posibles combinaciones.
Spoiler Inside | SelectShow> |
---|---|
public class Ejercicio_recursividad_DDR_33 { public static void main(String[] args) { // Zonas donde puedo puntuar int zonas[] = {10, 25, 50, 75}; // numero de dardos que lanzo int dardos = 5; // Regiones con el numero de dardos en cada region int regionesDadas[] = new int[zonas.length]; // puntuacion que se debe llegar int puntuacion = 100; int etapa = 0; dardosV2(zonas, regionesDadas, dardos, etapa, 0, puntuacion); } public static void dardosV2( int[] zonas, int[] regionesDadas, int dardos, int etapa, int puntuacionActual, int puntuacionIgualar ) { if (dardos == 0 || etapa == zonas.length || calcularPuntuacion(zonas, regionesDadas) == puntuacionIgualar) { if(calcularPuntuacion(zonas, regionesDadas) == puntuacionIgualar){ mostrarSolucion(zonas, regionesDadas); } } else { for (int d = 0; d <= dardos; d++) { int puntuacionZona = zonas[etapa] * d; int puntuacionRestante = puntuacionActual + puntuacionZona; if(puntuacionRestante <= puntuacionIgualar){ regionesDadas[etapa] = d; dardosV2( zonas, regionesDadas, dardos - d, etapa + 1, puntuacionActual + puntuacionZona, puntuacionIgualar ); regionesDadas[etapa] = 0; } } } } /** * Calcula los puntos de las zonas segun las regiones dadas * * @param zonas * @param regionesDada * @return */ public static int calcularPuntuacion(int[] zonas, int[] regionesDada) { int puntos = 0; // Recorro las regiones donde tengo el numero de dardos for (int i = 0; i < regionesDada.length; i++) { // Sumo los puntos puntos += zonas[i] * regionesDada[i]; } return puntos; } /** * Muestra el resultado segun los dardos usados Por ejemplo: 0 2 1 0 * (regiones) => 25 25 50 * * @param zonas * @param regionesDada */ public static void mostrarSolucion(int[] zonas, int[] regionesDada) { // Recorro las regiones donde tengo el numero de dardos for (int i = 0; i < regionesDada.length; i++) { // Si es distinto de cero if (regionesDada[i] != 0) { // muestro la zona repetida tantas veces como dardos haya for (int j = 0; j < regionesDada[i]; j++) { System.out.print(zonas[i] + " "); } } } System.out.println(""); } } |
7) Tenemos una diana con i regiones distintas cada una con una puntuación Ri(por ejemplo 4 regiones de valores 10,25,50 y 75puntos), y disponemos de D dardos (por ejemplo 5) para alcanzar una cierta puntuación P (por ejemplo, 100 puntos).
Saca la solución con menos dardos usados.
Spoiler Inside | SelectShow> |
---|---|
package ejercicio_recursividad_ddr_34; public class Ejercicio_recursividad_DDR_34 { public static void main(String[] args) { // Zonas donde puedo puntuar int zonas[] = {10, 25, 50, 75}; // numero de dardos que lanzo int dardos = 5; // Regiones con el numero de dardos en cada region int regionesDadas[] = new int[zonas.length]; // puntuacion que se debe llegar int puntuacion = 100; int etapa = 0; // Mejor solucion int mejorSolucion[] = new int[zonas.length]; dardosV3(mejorSolucion, zonas, regionesDadas, dardos, etapa, 0, puntuacion); mostrarSolucion(zonas, mejorSolucion); } public static void dardosV3( int[] mejorSolucion, int[] zonas, int[] regionesDadas, int dardos, int etapa, int puntuacionActual, int puntuacionIgualar ) { if (dardos == 0 || etapa == zonas.length || calcularPuntuacion(zonas, regionesDadas) == puntuacionIgualar) { if(calcularPuntuacion(zonas, regionesDadas) == puntuacionIgualar){ int sumaActual = sumaDardos(regionesDadas); int sumaMejor = sumaDardos(mejorSolucion); if(sumaMejor == 0 || sumaActual < sumaMejor){ for (int i = 0; i < mejorSolucion.length; i++) { mejorSolucion[i] = regionesDadas[i]; } } } } else { for (int d = 0; d <= dardos; d++) { int puntuacionZona = zonas[etapa] * d; int puntuacionRestante = puntuacionActual + puntuacionZona; if(puntuacionRestante <= puntuacionIgualar){ regionesDadas[etapa] = d; dardosV3( mejorSolucion, zonas, regionesDadas, dardos - d, etapa +1, puntuacionActual + puntuacionZona, puntuacionIgualar ); regionesDadas[etapa] = 0; } } } } /** * Devuelve la suma de dardos usados en cada una de las regiones Por * ejemplo: 2 dardos en 25 1 dardo en 50 ... * * @param regionesDada * @return */ public static int sumaDardos(int[] regionesDada) { int suma = 0; for (int i = 0; i < regionesDada.length; i++) { suma += regionesDada[i]; } return suma; } /** * Calcula los puntos de las zonas segun las regiones dadas * * @param zonas * @param regionesDada * @return */ public static int calcularPuntuacion(int[] zonas, int[] regionesDada) { int puntos = 0; // Recorro las regiones donde tengo el numero de dardos for (int i = 0; i < regionesDada.length; i++) { // Sumo los puntos puntos += zonas[i] * regionesDada[i]; } return puntos; } /** * Muestra el resultado segun los dardos usados Por ejemplo: 0 2 1 0 * (regiones) => 25 25 50 * * @param zonas * @param regionesDada */ public static void mostrarSolucion(int[] zonas, int[] regionesDada) { // Recorro las regiones donde tengo el numero de dardos for (int i = 0; i < regionesDada.length; i++) { // Si es distinto de cero if (regionesDada[i] != 0) { // muestro la zona repetida tantas veces como dardos haya for (int j = 0; j < regionesDada[i]; j++) { System.out.print(zonas[i] + " "); } } } System.out.println(""); } } |
Espero que os sea de ayuda. Si tenéis dudas, preguntad. Estamos para ayudarte.
Hola buenas, tengo una duda, y si no te dijeran a priori el tamaño del array, por ejemplo lo lees desde un .txt, lo he intentado implementar pero no me sale la lectura del fichero. ¿Podrías ayudarme? Por favor, gracias.
Me refiero al ejercicio de las becas y etapas de backtraking.