Descripción
del problema
El problema consiste en llenar una mochila con unos
objetos dados. Cada objeto tiene un tamaño y un valor. Lo
que se quiere conseguir es maximizar la suma del
tamaño*valor de todos los objetos introducidos en
la mochila. En el caso de que un objeto no se pueda meter entero,
se fraccionará, quedando la mochila totalmente llena.
Limitaciones de la solución: El algoritmo esta
implementado utilizando un array, por lo que en la
búsqueda para obtener el mejor objeto, se recorren incluso
los elementos que ya han sido insertados en la mochila. El
algoritmo se podría mejorar utilizando una cola de
prioridad. Solución: Para resolver el
problema utilizamos un algoritmo voraz. Las principales
operaciones que realiza el algoritmo son:
- Seleccionar aquel objeto que mejor cumpla una
condición (se darán varias opciones al
usuario): - aquel objeto cuyo valor sea el máximo,
- el objeto de mínimo peso, o
- el objeto con mayor valor por unidad de peso.
- Colocar en la mochila el objeto entero, o una
fracción en el caso de que sea demasiado grande. - Detener el algoritmo, cuando la mochila este llena.
Los datos de los objetos (peso y valor), se cargan desde
un fichero de texto. La primera fila de dicho fichero contiene
los pesos de los objetos, y la segunda fila los valores, todos
ellos separados por espacios en blanco. En la solución
planteada, se permite llenar la mochila dependiendo del valor de
los objetos, el peso o el valor por unidad de peso, sin embargo,
sólo esta ultima condición, garantiza que la
solución sea
óptima.
Código fuente:
public class Mochila {
private float pesos[];
private float valores[];
private float pesoMaximo;
private boolean descartados[];
private float pctSeleccionados[];
private int numObjetos;
public Mochila(float pesos[], float valores[], float pesoMaximo) {
if (pesos.length != valores.length) {
throw new IllegalArgumentException("pesos.length != valores.length");
}
numObjetos = pesos.length;
this.pesos = pesos;
this.valores = valores;
this.pesoMaximo = pesoMaximo;
pctSeleccionados = new float[numObjetos];
descartados = new boolean[numObjetos];
}
public float[] getSolucion() {
return pctSeleccionados;
}
/*Se invoca al algoritmo según la función de selección
*SELECCIÓN: 1-Mayor valor 2-Menor peso 3- Mayor valor por unidad de peso
*Devuelve una matriz con los trozos a tomar de cada elemento (en orden)
*/
public float[] algoritmo(int seleccion) {
int i = 0;
float pesoActual = 0;
for (int j = 0; j < numObjetos; j++) {
pctSeleccionados[j] = 0; // 0% de cada objeto
descartados[j] = false; // todos disponibles
}
do {
System.out.println("Solicitamos nuevo objeto…");
System.out.println("pesoMaximo=" + pesoMaximo);
System.out.println("pesoActual=" + pesoActual);
i = mejorObjeto(seleccion);
System.out.println("pesos[" + (i + 1) + "]=" + pesos[i]);
if (pesoActual + pesos[i] <= pesoMaximo) {
System.out.println("pesoActual + pesos[" + (i + 1) + "] <= pesoMaximo");
pctSeleccionados[i] = 100; // se coge el objeto entero (100%)
pesoActual += pesos[i];
}
else {
System.out.println("npesoActual + pesos[" + (i + 1) + "] > pesoMaximo");
pctSeleccionados[i] = ( (pesoMaximo – pesoActual) * 100 / pesos[i]);
pesoActual = pesoMaximo;
}
System.out.println("npesoActualizado=" + pesoActual);
System.out.println("Cogemos el " + pctSeleccionados[i] +
"% del elemento " + (i + 1));
System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
}
while (pesoActual < pesoMaximo);
return pctSeleccionados;
}
private int mejorObjeto(int seleccion) {
int indiceMejorObjeto = 0;
switch (seleccion) {
case 1: // Mayor valor
indiceMejorObjeto = maximoValor();
break;
case 2: // Menor peso
indiceMejorObjeto = minimoPeso();
break;
case 3: //Mayor valor por unidad de peso
indiceMejorObjeto = maximoValorPorUnidadDePeso();
break;
}
descartados[indiceMejorObjeto] = true;
return indiceMejorObjeto;
}
private int maximoValor() {
int indiceMejorObjeto = 0;
float maxValor = Float.MIN_VALUE;
for (int i = 0; i < numObjetos; i++) {
if (!descartados[i] && valores[i] > maxValor) {
indiceMejorObjeto = i;
maxValor = valores[i]; // se actualiza el maximo
}
}
return indiceMejorObjeto;
}
private int minimoPeso() {
int indiceMejorObjeto = 0;
float minPeso = Float.MAX_VALUE;
for (int i = 0; i < numObjetos; i++) {
if (!descartados[i] && pesos[i] < minPeso) {
indiceMejorObjeto = i;
minPeso = pesos[i]; // se actualiza el minimo
}
}
return indiceMejorObjeto;
}
private int maximoValorPorUnidadDePeso() {
int indiceMejorObjeto = 0;
float maxValorRelativo = Float.MIN_VALUE;
float valorRelativoActual;
for (int i = 0; i < numObjetos; i++) {
if (!descartados[i]) {
valorRelativoActual = valores[i] / pesos[i];
if (valorRelativoActual > maxValorRelativo) {
indiceMejorObjeto = i;
maxValorRelativo = valorRelativoActual; // se actualiza el maximo
}
}
}
return indiceMejorObjeto;
}
}
Complejidad: El caso peor supone que caben todos en la
mochila: O (n2).La complejidad se podría mejorar si los
objetos se almacenan en un montículo: O(n*Log(n))
Algoritmo
Heurístico
En computación, dos objetivos fundamentales para
la mayoría de casos son encontrar algoritmos con buenos
tiempos de ejecución y buenas soluciones, usualmente las
óptimas. Una heurística es un
algoritmo que ofrece uno o ambos objetivos; por ejemplo,
normalmente encuentran buenas soluciones, aunque en ocasiones no
hay pruebas de que la solución no pueda ser
arbitrariamente errónea; o se ejecuta razonablemente
rápido, aunque no existe tampoco prueba de que deba ser
así.
Página siguiente |