min(M - a1*b1 - a2*b2 - a3*b3)
a1, a2, a3 >= 0
recursive:
F(M, 0, 0, 0) = M
F(M, 1, 1, 1) = M - b1 - b2 - b3
recusrive solution: min F(M=const, a1, a2, a3) Forall possible a1, a2, a3
dynamic:
overlaping subproblems? && optimal substructure?
let total_spent = max(a1*b1 + a2*b2 + a3*b3)
we need to find min(M - total_spent) := min(M - max(a1*b1 + a2*b2 + a3*b3))
// brute-force recursive with memoization
Z(current_min, a1, a2, a3)
{
if current_min == 0 return [current_min, a1, a2, a3];
if current_min < b1 || current_min < b2 || current_min < b3 return [current_min, a1, a2, a3];
Z_B1 := Z(current_min - b1, a1 + 1, a2, a3);
Z_B2 := Z(... ...);
Z_B3 := ....
current_solution_for_this_current_min := MIN(Z_B1, Z_B2, Z_B3);
memoization[current_min] := current_solution_for_this_new_minimum;
return memoization[current_min];
}
ili bottom-up:
F(M, 0, 0, 0) = M
F(M, a1, a2, a3)
{
if M <= 0 return/output solution current tuple [a1,a2,a3]
if memoization[M] is defined return memoization[M];
// else compute
let take_b1 := F(M - B1 > 0, a1+1, a2, a3), take_b2 := F(M - B2, a1, a2+1, a3), take_b3 := F(M - B3, a1, a2, a3+1);
let min = min(take_b1, take_b2, take_b3);
memoization[M] := min
return min
}
ili
F(M=0) = 0
F(M=x)
{
if( M >= B1) F_B1:= F(M - B1) else F_B1:=M(=x)
if( M >= B2) F_B2:= F(M - B2) ...
if( M >= B3) F_B3:= F(M - B3) ...
memo, taken[at M=x] := min(F_B1, F_B2, F_B3), argmin(F_B1, F_B2, F_B3)
return memo, save taken in 'global' table (in order to 'recalculate the resulting triplet');
}