O problema da mochila 0/1 pode ser a princípio resolvido por 2 algoritmos (recursivo ou programação dinâmica)
Em termos de performance o algoritmo recursivo é muito ineficiente, “pendurando” na resolução de vários problemas
não muito complexos. O algoritmo que utiliza programação dinâmica pode não ser lá tão eficiente, mas é infinitamente
mais eficiente que o algoritmo recursivo (mochila recursiva)
O algoritmo de programação dinâmica [CLR 17.2-1] consome O(nW) unidades de tempo. Mas isso só é possível se W,
w[1],…,w[n] forem todos inteiros não-negativos.
A execução do algoritmo usando PD (programação dinâmica) se faz através da recurção em iteração com apoio de uma
tabela. Na tabela t[m][n] são guardadas todas as soluções em instância possíveis.
Variável Descrição
int w[] Vetor contendo os pesos (weight) de cada um dos itens
int v[] Vetor contendo os valores (values) de cada um dos itens
int n Número de itens que serão trabalhados
int W Peso total (capacidade da mochila)
Um exemplo clássico da aplicabilidade deste algoritmo é o que lhe dá o nome (capítulo 16 - Th.H. Cormen, Ch.E.
Leiserson, R.L. Rivest, C. Stein ), onde um ladrão de obras de artes entra em uma galeria com uma maleta de tamanho
x. Obviamente ele quer carregar o máximo de valor em obras de artes que caibam em sua maleta. O algoritmo da
mochila é usado para resolver este problema. Segue uma ilustração.
Tem-se um mochila com capacidade para carregar 5 quilos e um total de 4 itens, cujos pesos e valores são os seguintes:
Peso Valor Obviamente, segundo estes itens ao lado esquerdo, a melhor combinação a carregar seria
4 500 o segundo e o quarto item (R4 400,00 + R$ 450,00) totalizando R$ 850,00.
2 400
1 300 Note que pelo peso, poderia-se pegar o item de valor R$ 500,00 + R$ 300,00 (5 kg)
3 450 ou R$ 450,00 +R$ 300,00 (4 kg). Porém, nenhuma destas é a melhor escolha.
Suponha que W = 5 e n = 4. Os vetores w e v são dados pela figura esquerda. A figura direita dá a tabela t.
1 2 3 4 0 1 2 3 4 5
w 4 2 1 3 0 0 0 0 0 0 0
v 500 400 300 450 1 0 0 0 0 500 500
2 0 0 400 400 500 500
3 0 300 400 700 700 800
4 0 300 400 700 750 850
O número de linhas será sempre a quantidade de itens (n) e o número de colunas será sempre o W, que seria o tamanho
da mochila. Note que o maior valor possível sempre estará na posição t[n][W] (última linha e coluna à direita).
Em muitos problemas, além de saber quanto é possível carregar na mochila, necessita-se saber quais valores serão
selecionados pelo algoritmo. Isso é muito simples de se obter através da tabela t (a mesma tabela do exemplo anterior).
O procedimento para isso é listado abaixo:
a) define-se um vetor x[maxobjetos] que conterá 1 ou 0 para cada posição indicando, respectivamente, se o valor
correspondente do vetor w deve ser selecionado ou não. Neste caso é x[5] e se ocupa as posições de 1 a 4.
b) partindo-se do elemento inferior direito (último da matriz t) diminui-se o valor selecionado (w[i]) da coluna, caso ele
seja diferente do elemento da linha anterior. Neste caso, 850 é diferente de 800, portanto coloca-se o valor 1 em x[4] e
diminui-se 3 (w[i]) do y.
c) repete-se o procedimento enquanto a linha for maior do que 0
Volta 2 colunas (0)
1 2 3 4 t 0 1 2 3 4 5
w 4 2 1 3 0 0 0 0 0 0 0
v 500 400 300 450 1 0 0 0 0 500 500
2 0 0 400 400 500 500
3 0 300 400 700 700 800
4 0 300 400 700 750 850 Volta 3 colunas (2)
Por último, pode-se desejar somar o total em peso colocado na mochila. Isso se deve ao fato de que mesmo que a
mochila tenha capacidade para 5 kg, pode ser que devido aos objetos, seja colocado na mesma menos do que isso
(4,3,2,...etc).
int peso=0;
for (int i = 1; i<=n; i++) {
if (x[i]==1) {
peso += w[i]; // 2 + 3 = 5
}
}
PS.: Note que neste caso específico não precisamos saber quais os produtos foram pegos, ou seja, não há necessidade
de utilizar a segunda parte do algoritmo.
#include <iostream>
int a,b,t[MAXOBJ][MAXCARGA],x[MAXOBJ];
int main(){
int w[MAXOBJ],v[MAXOBJ];
int objetos,carga,total;
cin >> objetos;
for (int i=1; i<=objetos; i++){
cin >> v[i];
cin >> w[i];
}
cin >> carga;
total = mochila(w,v,objetos,carga);
cout << total << endl;
return(0);
}