Liu zitao
Dynamic Planning, Dynamic Programming. The programming here is not translated into programming because the programming here refers to a tabular method. In fact, this also implies the nature of DP, using a table to store the intermediate results of the subproblem. (Examples will be provided later)
It is similar to the divide and conquer algorithm, but the difference is that the divide and conquer algorithm divides the original problem into several independent subproblems to solve them one by one, dynamic Planning is a solution for overlapping sub-problems.
Currently, design DP has two main ideas:
One is to use the recursive method, that is, to solve the problem first using a recursive method, and then use a table to save the intermediate results in the recursive. Does this avoid the inefficiency of repeated calculation in recursion? If you need to calculate something you have previously computed, you can directly look up the table. In a word, you can write recursive first, and then you can write the DP Method better than Hulu. The difficulty here is how to find the recursive. This idea is also provided in the introduction to algorithms. The first three examples are all from introduction to algorithms.
Another idea is exhaust search, which seems to be a method invented by our teacher. Here is a Kirk paper,How to design dynamic programming algorithms sans recursionIf you are interested, you can take a closer look. I will also give a brief example of this method.
In the following example, most of the Code is pseudo code, which is designed to define strate idea. Saves time. The backtrack process is saved in the code, that is, the value of optimal solution is obtained, and the process of construct optimal solution is saved. This usually uses an array to record it.
First, let's look at a simple example (in fact, it's not hard for O (∩) O ~)
Example: Rod-cutting problem(Wood cutting problem. How does it feel changed after translation? Success ...)
Input: There is a n-meter-long wood, and a price table, the table is as follows:
Length I 1 2 3 4 5 6...
Price Pi 1 5 8 9 10 17...
Obviously, wood with a length of 1 meter can be bought for 1 yuan, and wood with a length of 5 meters can be sold for 10 yuan, and so on.
Output: Find a cut method to make the most money.
Obviously, the main idea of recursion is that after I cut a knife, I divided it into two sections. I sold it at the table price, and I considered it a new subproblem, continue as a new parameter of my function. Isn't it recursive? (* ^__ ^ *) But the problem is how to cut the knife. That's right. Let's find the maximum value, that is, max _ {I = 1 to n} Pi + Cut (n-I ).
Therefore, recursive functions should be:
Cut (P, n ){//P is my table, n is the length of wood
IfN= 0
Return 0;
Q= -Infinity
ForI= 1To n
Q=Max (q, P [I]+Cut (P, n-I ))
ReturnQ;
}
Then, write DP Based on the recursive
Cut (P, n ){
For (int I = 1; I <= n; I ++ ){
Q =-infinity;
For (int j = 1; j <= I; j ++)
Q = max (q, P [j] + r [I-j]);
R [I] = q;
}
Return r [n];
}
Example: Longest common Longest subsequence problem
Problem description: this, very... Obviously, I don't know ,... HereHttp://en.wikipedia.org/wiki/Longest_common_subsequence_problem
Of course, here we also need to find recursion first. Suppose I have two sequence, one is X, the length is n, the other is Y, and the length is m.
Now suppose I have two points. One is I, which refers to the last element of X and the other is j, which refers to the last element of Y. Our recursion is divided into three situations.
1) if X [I] = Y [j] Then LCS (X [I], Y [j]) = LCS (X [I-1], Y [J-1]) + 1
This is obvious, because a group of public elements is found, it depends on the number of public elements remaining.
2) If X [I]! = Y [j] So LCS (X [I], Y [j]) = max (LCS (X [I-1], Y [j]), LCS (X [I], Y [J-1])
This is also very easy to be the same, that is, if we find different, we will remove the last one of X or Y, and then compare it with another complete one. In this way, we will remove X or the last one of Y, there are two possibilities, so we need to find one of max in the middle.
3) if I = 0 or j = 0, return 0
Because a sequence is complete.
So recursion is obvious here:
LCS (n, m ){
If m = 0 | n = 0
Return 0;
If (X [n] = Y [m])
Return LCS (N-1 m-1) + 1;
Else
Return max (LCS (m-1), LCS (n-1, m ));
}
Now with recursion, we should be able to write it into the tabular DP.
Initialization: the first column in the first row of Table LCS is set to 0.
For I = 1 to m
For j = 1 to n
If (X [I] = Y [j])
LCS [I, j] = LCS [I-1, J-1] + 1;
Else
LCS [I, j] = max (LCS [I, J-1], LCS [I-1, j]);
For example, the problem of multiplication of matrix chains to the minimum number of times
Here is a detailed description of the problem.Http://en.wikipedia.org/wiki/Matrix_chain_multiplication
First, let's formalize our input, matrix Chain {A1, A2,..., An}. For matrix Ai, It is a matrix of Pi-1 * Pi. M [I, j] indicates the minimum multiplication times of {Ai, Ai + 1,..., Aj} multiplied (strongly calls for a plug-in similar to Latex)
The idea of recursion is actually a bit similar to that of the first question. Let's first look at how to recursion.
First, we need to find a point to separate the chain, this is equivalent to converting this problem to the problem of least multiplication of the matrix chain in the first part of the point and the problem of least multiplication of the matrix chain in the last part of the point.
But how can I find this point? Like in the first example, we can directly traverse and find.
So our recursion should be like this:
M [I, j] = min _ {I <= k <= j} (m [I, k] + m [k + 1, j] + Pi-1 * Pk * Pj)
Of course, this is for I! = J. What happens when I = j? It is obviously 0, because our matrix chain is just a matrix.
That is
Matrix-chain (I, j ){
If (I = j)
Return 0;
Q = infinity;
For k = I to j
Q = min (q, Matrix-chain (I, k) + Matrix-chain (k + 1, j) + Pi-1 * Pk * Pj );
Return q;
}
Now, we can turn this recursive item into DP. There is specific code in the introduction to algorithms. Here we only write a brief introduction.
Let's assume that we save the intermediate result as an n * n table m.
Initialization: m is initialized to 0.
For l = 2 to n
For I = 1 to n-l + 1
J = I + L-1
M [I, j] = infinity
For k = I to J-1
Q = m [I, k] + m [k + 1, j] + Pi-1 * Pk * Pj;
If (q <m [I, j])
M [I, j] = q;
Return m
Refer to the recursive example above. This DP code is not hard to understand.
Longest return sequence
The back-to-source sequence is the same for reading from left to right and from right to left. For example, civic, racecar, and aibohphobia. All strings with a length of 1 are input.
The objective is to give a string to find the longest return sequence of the string, such as character and carac.
The following describes the method invented by our teacher,Exhausted search addition and subtraction~ OrExhaust search with pruningNice to listen to O (∩ _ ∩) O ~
The main idea of this method is to first construct a tree to make the leaf node of the tree a possible final solution, in other words, the final answer must exist in a leaf node at the bottom of the tree. Obviously, in general, this tree is still relatively well constructed. After all, there is no need to consider any conditions, that is, an exhaust expansion process. But as the tree expands, the branches become more and more, this certainly does not make sense, so we need to find some pruning rules to trim this tree. In fact, after half a day, it must be vague. Let's take a look at the example first. I think it is quite a bit of a sense to read the example later.
Longest incremental string for Example
Problem description:Http://en.wikipedia.org/wiki/Longest_increasing_subsequence_problem(Obviously)
Assume that one of my input strings is X1, X2, X3,..., Xn, And we construct an enumeration tree ).
How to construct this tree