Introduction
Dynamic programming is a way to solve complex problems by breaking them down into simpler subproblems.
The Turtle Problem
A table of rows and columns is given. In each cell , where , , there are coins.
Dynamic programming is a way to solve complex problems by breaking them down into simpler subproblems.
A table of rows and columns is given. In each cell , where , , there are coins.
Solve these external problems (e.g., from Codeforces) to reinforce the lesson material:
In the upper left corner there is a turtle, that is, in the cell . The turtle can move only down or to the right. The turtle needs to reach the cell , collecting the maximum number of coins.

How do we solve this problem? Let’s first try to solve it using recursion.
Let denote the maximum number of coins that the turtle can collect if it starts from and reaches the cell . Then the answer will be .
Now let’s return to dynamic programming. The principle of DP is very similar to the principle of recursion.
Let’s recall what DP is: dynamic programming is a way to solve a problem by breaking it down into simpler subproblems.
That is exactly what we did above. To find the answer (for or ) we computed the values of simpler problems — and .
In this case:
Usually, when solving dynamic programming problems, the following logic is followed:
A question arises: what, then, is the difference between dynamic programming and recursive brute force?
In both cases we have states and transitions between them.
The difference is that in dynamic programming the same states are not computed multiple times, whereas in ordinary recursion they can be computed repeatedly.
Let’s recall the lesson on recursion with memorization (memoization), where we discussed why recursion can recompute the same values and how to solve this problem.
The same idea can be applied here as well. If we add memorization to the recursive solution, then we will effectively get a solution using dynamic programming.
The turtle found an array of numbers. The turtle needs to choose some subset of these numbers so that their sum is maximal among all possible options.
However, there is a restriction: you cannot choose two adjacent numbers at the same time.
How do we solve this problem?
Let’s find the DP states. Let be the maximum sum that the turtle can collect using only the elements of the prefix of length .
That is, we consider the array .
Base cases:
Now consider how to compute for . Two options are possible:
The turtle takes the number at position .
Then it cannot take , so it can use only the prefix
.
The sum in this case is .
As a result, we obtain the DP formula:
The answer to the original problem will be the value .
The turtle does not take the number at position .
Then it can use the prefix
, and the sum is .
int Rec(int x, int y) {
if (x == 1 && y == 1) {
return C[1][1];
} else {
int best = 0;
if (x > 1) {
best = max(best, Rec(x - 1, y));
}
if (y > 1) {
best = max(best, Rec(x, y - 1));
}
return best + C[x][y];
}
}
map<pair<int, int>, int> mem;
int Rec(int x, int y) {
if (x == 1 && y == 1) {
return C[1][1];
} else {
if (mem.find({x, y}) != mem.end()) {
return mem[{x, y}];
}
int best = 0;
if (x > 1) {
best = max(best, Rec(x - 1, y));
}
if (y > 1) {
best = max(best, Rec(x, y - 1));
}
return mem[{x, y}] = best + C[x][y];
}
}
dp[0] = 0;
dp[1] = a[1];
for (int i = 2; i <= n; i++) {
dp[i] = max(dp[i - 2] + a[i], dp[i - 1]);
}