Veamos primero la solución recursiva al problema.
Aquí, consideramos que wt[i]
denota el costo de i-party, y val[i]
denota el valor divertido para i-party. W
denota el costo máximo proporcionado. N
es el número total de partes.
Definamos una función int
knapSack(
int
W,
int
wt[],
int
val[],
int
n)
, que devolverá la máxima “diversión” que puede obtenerse de un máximo de ” W
” costo n
número de partes .
¿Cuál debería ser el caso base para la función recursiva anterior? Obviamente, si el costo máximo que se nos da es cero ( W==0
), entonces no podremos participar en ninguna fiesta, lo que obviamente no es divertido, por lo tanto, la diversión máxima en este caso es 0. Además, si el número de fiestas es cero, no tendremos la oportunidad de divertirnos ( n==0
). Por lo tanto, el caso base de la función es
- Probablemente moriré en unos pocos meses de cáncer. ¿Qué puedo hacer para aliviar el dolor en mi familia?
- Cómo aprender a hablar inglés tan fluidamente como puedo escribir inglés, dado que el inglés no es mi lengua materna y puedo entender el inglés escrito como un nativo
- Si compro un cajero automático nuevo, ¿cómo creo un software personalizado para él?
- Tengo B1visa de EE. UU. Hasta el 31 de mayo de 16. Le di I-94 durante 6 meses a EE. UU. Quería viajar a México. Cuando vuelva a ingresar a EE. UU., ¿Cambiará mi fecha I-94?
- ¿Qué puedo hacer para evitar que mi conejo se vaya al baño en mi cama?
if
(n == 0 || W == 0)
return
0;
Ahora para la siguiente parte. Tenemos suficiente dinero y suficientes fiestas. Ahora, ¿qué pasa si el costo de la enésima parte ( wt[n-1
) en sí es mayor que el costo de todo el presupuesto ( W
) que se nos proporciona? No tiene sentido llorar desesperadamente por algo que no puedes conseguir. Sabes que es hora de olvidar y seguir adelante con lo que Dios te ha dado en lugar de culparlo por las cosas que no te dio. Entonces, la cantidad de “diversión” que obtienes es independiente de si consideras la enésima fiesta o no. Entonces, reducimos el número de cálculos al eliminar los imposibles.
if
(wt[n-1] > W)
return
knapSack(W, wt, val, n-1);
Ahora que tiene suficiente dinero para ir a la enésima fiesta, todavía no está satisfecho. Desea divertirse tanto como quiera con el dinero limitado que tiene. Entonces, siéntate cerca de la puerta de entrada con un bolígrafo y papel y comienza a calcular si vale la pena ingresar a esta enésima fiesta o no. Tienes 2 opciones:
i) Ingrese a esta enésima fiesta, gaste el dinero ( wt[n-1]
), diviértase que esta enésima fiesta le puede dar, y luego salga de la fiesta con su bolsillo menos pesado (dinero restante = W-wt[n-1]
). Sin embargo, te divertiste un poco ( val[n-1]
), y tienes n-1
fiestas más para satisfacer tu interminable enfriamiento de diversión. Entonces, considerando que tomaste esta decisión, ¿qué devolverá la función actual? Respuesta: val[n-1] + knapSack(W-wt[n-1], wt, val, n-1)
ii) O puede ignorar esta fiesta y buscar las otras n-1
, pero esta vez, su bolsillo está lleno del dinero original W
, pero aún no se ha divertido. Entonces esto debería devolver knapSack(W, wt, val, n-1)
Entonces, considerando las dos opciones anteriores, ¿cuál debería tomar? ¡Obviamente el que te brinda más diversión! Entonces, la declaración final se verá así:
else return max( val[n-1] + knapSack(W-wt[n-1], wt, val, n-1),
knapSack(W, wt, val, n-1)
);
El enfoque Greedy completo se parece a esto
int knapSack (int W, int wt [], int val [], int n)
{
si (n == 0 || W == 0)
devuelve 0;
si (wt [n-1]> W)
return knapSack (W, wt, val, n-1);
de lo contrario, devuelve max (val [n-1] + knapSack (W-wt [n-1], wt, val, n-1),
knapSack (W, wt, val, n-1)
);
}
Pero no desea perder tanto tiempo para calcular las mismas cosas una y otra vez donde debería divertirse tanto. Entonces, necesitas la ayuda de DP. Del enfoque codicioso queda claro que para calcular la diversión para la enésima fiesta, primero debemos calcular la diversión para la fiesta n-1. Entonces, para reducir los cálculos, almacenamos los valores de los valores más bajos en una matriz 2D, de modo que no tengamos que calcular los valores anteriores una y otra vez. Entonces tomamos una matriz 2D K [n + 1] [W + 1]. Ahora, ¿qué denota K [i] [j]? K [i] [j] denota la cantidad de diversión que tendremos, teniendo en cuenta que hay i (el número de fila) número de fiestas, y j (el número de columna) es el Peso total que se nos otorga (desglosando así el problema). Considere el ejemplo, val[]={1,4,5,7}
y wt[]={1,3,4,5}
. K[0][0]
será igual a cero (caso base). En cambio, si cualquiera de i
o j
es 0, K[i][j]
es igual a 0. ¿Qué denotará K [1] [1]? La cantidad máxima de diversión que puede obtener cuando solo hay 1 parte de valor de diversión val[1-1]
y el costo de entrada es wt[1-1]
, y su presupuesto total es 1. ¿Qué es K [1] [2] ? La cantidad máxima de diversión que puede obtener cuando solo hay 1 parte de valor de diversión val[1-1]
y el costo de entrada es wt[1-1]
, y su presupuesto total es 2. De esta manera, completa la matriz según la fórmula dorada – K[i][w]=max(val[i-1]+K[i-1][j-wt[i-1]],K[i-1][j]);
¿Cuál es la respuesta final? La máxima diversión que tuvo considerando n cantidad de fiestas y W como el dinero total que le dieron. ¿Dónde debería estar la respuesta en la matriz? K[n][W]
.
Luego viene cómo calcular el peso óptimo. Cree otra matriz int wg[n+1][W+1]
que almacenará el peso óptimo para su fila y columna correspondiente en la matriz K[][]
. wg[i][j]
calcula el peso total para i
no de las partes y j
cantidad de costo. Para obtener un valor óptimo, encuentre el valor mínimo de los elementos en la última fila (enésima fila), y ese valor mínimo es la solución óptima.
EDITAR: No se requiere una nueva matriz. Lo mismo se puede hacer con la matriz K[][]
Puede consultar mi solución aquí: RudraNilBasu / C-CPP-Codes o una discusión más detallada sobre 0/1 Mochila – Programación dinámica | Conjunto 10 (problema de mochila 0-1) – GeeksforGeeks.