Dynamic programming is a technique for solving problems recursively, with overlapping
sub-problems. This approach works only when the solution to sub-problems share the same structure with the final solution. If the prerequisite is
satisfied, the conceptual way of solving the problem is to derive the recursion, and builds up the result bottoms-up. Some examples are listed
below.

Knapsack

Problem spec:

Given a set of items, each of which is associated with some weight and value. Find the subset of items which can be carried into the knapsack with
weight limit W. It is required that the cumulative value of the items in the knapsack is maximum value possible.

For analyzing the problem, letâ€™s focus on the last recursion step, i.e. deciding if last item (weight: 3, value: 50) should be selected. In this case,
we only have two options, select it or drop it, corresponding to max value obtained from selecting from the first three items with weight constraint
7, and selecting from the first three items with weight constraint 10.

m[i][j] = max value obtained from selecting up to i-th items with weight contraint j
m[i][j] = max(m[i-1][j-w_i], m[i-1][j] + v_i)

Given an array of non-negative integers and a pointer pointing at the zeroth slot of the array. The pointer can only incremented by 4 or 7, and such
process repeats until it goes beyond the bound of the array. Devise a moving strategy so that the sum of all slots the pointer pointed reaches the
maximum. Your solution should calculate this maximum.

Sample:

array = {1, 2, 3, 4, 5}
result = [0, 4]
sum = array[0] + array[4] = 6
array = {1, 2, 0, 4, 5, 3, 9, 8}
result = [0, 7]
sum = array[0] + array[7] = 9

List<LinkedList<Integer>> traces = loop(array.length, new ArrayList<LinkedList<Integer>>(Collections.singletonList( new LinkedList<>(Collections.singletonList(0)))));

int[] sums = newint[traces.size()];

for (int i = 0; i < traces.size(); ++i) { LinkedList<Integer> t = traces.get(i); for (Integer index : t) { assert index >= 0 && index < array.length; sums[i] += array[index]; } }

return Arrays.stream(sums).max().getAsInt(); }

privatestaticbooleanis_valid(int[] cost, int index){ return index >= 0 && cost[index] >= 0; }

privatestaticintlast_max(int[] cost){ if (cost.length <= 4) return cost[0];

privatestaticvoideq(int x, int y){ if (x != y) { System.exit(-1); } }

staticvoidrand_test(int size){ Random rand = new Random(); int[] array = newint[size]; for (int i = 0; i < size; ++i) { array[i] = rand.nextInt(100); }

int mine = hop(array); int correct = hop_force(array);