You are on page 1of 9

PROBLEMA DE LA MOCHILA

(KNAPSACK PROBLEM)

1. INTRODUCCIN
El problema de la mochila es un problema simple de entender: hay
una persona que tiene una mochila con una cierta capacidad y tiene
que elegir qu elementos pondr en ella. Cada uno de los elementos
tiene un peso y aporta un benecio. El objetivo de la persona es
elegir los elementos que le permitan maximizar el benecio sin
excederse de la capacidad permitida.
A la vez es un problema complejo, si por complejidad nos
referimos a la computacional. Un problema se cataloga como
inherentemente difcil si su solucin requiere de una cantidad
signicativa de recursos computacionales, sin importar el algoritmo
utilizado. El problema de la mochila forma parte de una lista
histrica de problemas NP Completos elaborada por Richard Karp
en 1972.
En el caso del problema de la mochila, si contramos con 4
productos, para saber cul es la mejor solucin podramos probar las
24 = 16 posibilidades. El 2 se desprende del hecho de que cada
decisin es incluir o no al producto y el 4 de la cantidad de
productos. 16 posibilidades es un nmero manejable, sin embargo, si
la cantidad de elementos por ejemplo ascendiera a 20, tendramos
que analizar nada ms y nada menos que 2 20 = 1,048,576
posibilidades.

2. DEFINICIN FORMAL DEL PROBLEMA


Supongamos que tenemos n distintos tipos de tems, que van del 1
al n. De cada tipo de tem se tienen qi tems disponibles, donde qi es
1 q i
un entero positivo que cumple:
Cada tipo de tem i tiene un beneficio asociado dado por vi y
un peso (o volumen) wi. Usualmente se asume que el benecio y el
peso no son negativos. Para simplicar la representacin, se suele

asumir que los tems estn listados en orden creciente segn el peso
(o volumen).
Por otro lado se tiene una mochila, donde se pueden introducir los
tems, que soporta un peso mximo (o volumen mximo) W.
El problema consiste en meter en la mochila tems de tal forma que
se maximice el valor de los tems que contiene y siempre que
no se supere el peso mximo que puede soportar la misma.
La solucin al problema vendr dado por la secuencia de
variables x1, x2, ..., xn donde el valor de xi indica cuantas copias se
metern en la mochila del tipo de tem i.
El problema se puede expresar matemticamente por medio del
siguiente programa lineal:
n

vi xi

Maximizar

i=1

vi xi W

Tal que

i=1

1 q i

Y
Si

qi =1

para i=1,2,...,n se dice que se trata del problema de la

mochilla 0-1. Si uno o ms

qi

es innito entonces se dice que se

trata del problema de la mochila no acotado tambin llamado a


veces problema de la mochila entera. En otro caso se dice que se
trata del problema de la mochila acotado.
3. ALGORITMO (PARADIGMA: DIVIDE AND CONQUER)
Para que el algoritmo propuesto funcione correctamente los
elementos a insertar en la mochila se han de ordenar en funcin de
la relacin peso/benecio:
b1 / p1 b 2 / p2 bn / pn
El Quicksort trabaja particionando el conjunto a ordenar en dos
partes, para despus ordenar dichas partes independientemente. El
punto clave del algoritmo est en el procedimiento que divide el

conjunto. El proceso de divisin del conjunto debe cumplir las


siguientes tres condiciones:
a. El elemento pivote=a[i] est en su posicin nal en el array para
algn ndice i.
b. Todos los elementos en a[rst], ..., a[i-1] son menores o iguales a
a[i].
c. Todos los elementos en a[i+1], ..., a[last] son mayores que a[i].
En este punto se aplica el mismo mtodo recursivamente a los dos
subproblemas generados: a[rst], ... , a[i-1] y a[i+1], ... , a[last]. El
resultado nal ser una matriz completamente ordenada, y por tanto
no hace falta un paso subsiguiente de combinacin.
4. EL ALGORITMO
A. ANLISIS DEL PROBLEMA
Para el anlisis tomaremos un caso en particular.
Sea el conjunto de elementos (6) con
caractersticas:

VALOR
PESO

0
50
60

1
40
40

2
30
20

3
66
30

las

4
20
10

siguientes

5
60
50

Y una mochila con capacidad de 100.


a. VORAZ SIN ORDENAMIENTO
Si tomamos los elementos tal cual son ingresados (sin
ordenamiento previo). Tomaramos los 2 primeros:
VALO
R
50
40

PESO
60
40

Valor mximo obtenido: 90


b. MAYOR VALOR

FRACCI
N
1
1

Si consideramos como parmetro de decisin el valor de los


objetos a escoger, tomaramos los siguientes elementos:
VALO
R
66
60
50

PESO
30
50
60

FRACCI
N
1
1
1/3

Para el caso de MOCHILA FRACCIONARIA debemos tomar


solo una porcin del ltimo elemento para no excedernos en
el peso.
Valor mximo obtenido: 142.667

Para el caso

VALO
R
66
60
30

PESO
30
50
20

de
MOCHILA
NO
FRACCIONARIA tomamos
el
siguiente
elemento con mayor valor
cuyo peso sea menor o igual al peso restante antes de
sobrepasar la capacidad de la mochila.
Valor mximo obtenido: 156

Observamos mejores resultados respecto del caso anterior.


c. MENOR PESO
Si consideramos como parmetro de decisin el menor peso de
los objetos a escoger, tendramos la siguiente solucin
VALO
R
20
30
66
40

PESO
10
20
30
40

FRACCI
N
1
1
1
1

Valor mximo obtenido: 156


Observamos mejores resultados respecto del caso anterior.

d. MEJOR RENTABILIDAD
Concluimos que si tomamos en cuenta algn parmetro de
ordenacin previa de los vectores PESO y VALOR obtenemos
mejores soluciones para el problema. Sin embargo, an
podemos optimizar la solucin si consideramos los dos
parmetros a la vez. Cmo? Relacionndolos. Cmo los
relacionamos? Con un nuevo parmetro al que llamaremos:
RENTABILIDAD, que viene a ser la relacin inversa entre VALOR
y PESO.
RENTABILIDAD=

VALOR
PESO

De esta manera generamos un nuevo vector RENTA a partir de


los 2 iniciales:

VALO
R
PESO
RENT
A

0
50

1
40

2
30

3
66

4
20

5
60

60
0.83

40
1

20
1.5

30
2.2

10
2

50
1.2

Para el caso de MOCHILA FRACCIONARIA tomaremos los


elementos siguientes:
RENT
A
2.2
2
1.5
1.2

VALO
R
66
20
30
60

PESO
30
10
20
50

FRACCI
N
1
1
1
4/5

Valor mximo obtenido: 164

Para el caso de MOCHILA NO FRACCIONARIA tomaremos los


elementos siguientes:

RENT
A
2.2
2
1.5
1

VALO
R
66
20
30
40

PESO
30
10
20
40

Valor mximo obtenido: 156


B. IMPLEMENTACIN DEL ALGORITMO
a. ORDENAMIENTO
Realizamos el ordenamiento mediante el algoritmo de
ordenamiento Quicksort basado en el paradigma DnC (Divide y
Conquer).
void quicksort(float v[], float w[],int inf,int sup)
{ int i,j,div; double pivote, tmp, tmp2, a, b;
div=(inf+sup)/2;
pivote=v[div]/w[div];
i=inf; j=sup;
do
{ while((v[i]/w[i])>pivote)i++;
while((v[j]/w[j])<pivote)j--;
if(i<=j)
{ tmp=v[j];
tmp2=w[j];
v[j]=v[i];
w[j]=w[i];
v[i]=tmp;
w[i]=tmp2;
i++; j--;
}
}while(i<=j);
if(inf<j) quicksort(v,w,inf,j);
if(i<sup) quicksort(v,w,i,sup);
}
b. SELECCIN DE ELEMENTOS
Implementamos un algoritmo simple para generar la
solucin con los vectores ya ordenados

Para el caso de MOCHILA FRACCIONARIA:

while(peso<capacidad&&i<n)
{ if(peso+w[i]<=capacidad)
solucion[i]=1;
else
solucion[i]=(capacidad-peso)/w[i];
peso=peso+w[i]*solucion[i];
i++;
}
Para el caso de MOCHILA NO FRACCIONARIA:
while(peso<capacidad&&i<n)
{ if(peso+w[i]<=capacidad)
solucion[i]=1;
peso=peso+w[i]*solucion[i];
i++;
}

ALGORITMO FINAL:
#include<conio.h>
#include<iostream>
using namespace std;
int n;
void quicksort(float v[], float w[],int inf,int sup)
{ int i,j,div; double pivote, tmp, tmp2;
div=(inf+sup)/2;
pivote=v[div]/w[div];
i=inf; j=sup;
do
{ while((v[i]/w[i])>pivote)i++;
while((v[j]/w[j])<pivote)j--;
if(i<=j)
{ tmp=v[j];
tmp2=w[j];
v[j]=v[i];
w[j]=w[i];
v[i]=tmp;
w[i]=tmp2;
i++; j--;
}
}while(i<=j);
if(inf<j) quicksort(v,w,inf,j);
if(i<sup) quicksort(v,w,i,sup);
}
/*---------------------------------------------------------*/
int main ()
{ int i, j;
float peso=0, valor=0, suma=0, capacidad;
system("color 0B");

cout<<"\n\n ---------------------[ KNAPSACK PROBLEM ]----------------------";


cout<<"\n
Divide and Conquer\n\n";
cout<<"\n\t CAPACIDAD DE LA MOCHILA: ";cin>>capacidad;
cout<<"\n\t CANTIDAD DE OBJETOS: ";cin>>n;
float w[n], v[n], solucion[n];
cout<<endl;
for(i=0;i<n;i++)
{ cout<<"\n\t Valor del objeto "<<i+1<<": "; cin>>v[i];
cout<<"\t Peso del objeto "<<i+1<<": "; cin>>w[i]; suma=suma+w[i];
}
if(suma>=capacidad)
{ for(i=0;i<n;i++)
solucion[i]=0;
quicksort(v,w,0,n-1);
i=0;
while(peso<capacidad&&i<n)
{ if(peso+w[i]<=capacidad)
solucion[i]=1;
else
solucion[i]=(capacidad-peso)/w[i];
peso=peso+w[i]*solucion[i];
i++;
}
system("cls");
cout<<"\n\n ---------------------[ MOCHILA FRACCIONARIA ]----------------------\n";
cout<<"\n\tRENTA\tPESO\tVALOR\tFRACCION PESO EN MOCHILA\n\n";
for(i=0;i<n;i++)
if(solucion[i])
{ cout<<"\t "<<v[i]/w[i]<<"\t "<<w[i]<<"\t "<<v[i]<<"\t "<<solucion[i]<<"\t\t
"<<w[i]*solucion[i]<<endl;
valor=valor+v[i]*solucion[i];
}
cout<<"\n\t\t\t\t VALOR LOGRADO: "<<valor;
/* mochila no fraccionaria*/
for(i=0;i<n;i++)
solucion[i]=0;
i=0; peso=0; valor=0;
while(peso<capacidad&&i<n)
{ if(peso+w[i]<=capacidad)
solucion[i]=1;
peso=peso+w[i]*solucion[i];
i++;
}
cout<<"\n\n\n\n ---------------------[ MOCHILA NO FRACCIONARIA ]----------------------\n";
cout<<"\n\tRENTA\tPESO\tVALOR\tFRACCION PESO EN MOCHILA\n\n";
for(i=0;i<n;i++)
if(solucion[i])
{ cout<<"\t "<<v[i]/w[i]<<"\t "<<w[i]<<"\t "<<v[i]<<"\t "<<solucion[i]<<"\t\t
"<<w[i]*solucion[i]<<endl;
valor=valor+v[i]*solucion[i];
}
cout<<"\n\t\t\t\t VALOR LOGRADO: "<<valor;
}
else cout<<"\n\n SOUCION TRIVIAL...";

getch();
return 0;
}

5. COMPLEJIDAD
En nuestro algoritmo la funcin del tiempo de ejecucin estara dada
por el algoritmo de ordenacin (Quicksort) y el de seleccin de los
elementos.
Como sabemos la complejidad de un Quicksort es O ( nlogn ) y por
simple inspeccin obtenemos la complejidad del algoritmo de
seleccin igual a O ( n ) . Entonces la funcin T.E. sera la siguiente:
T ( n ) =O ( nlogn ) +O(n)
Para efecto de simplicacin la complejidad de nuestro algoritmo sera
O ( nlogn )

You might also like