Dynamic Programming Learning: A detailed analysis of the tower problem

Source: Internet
Author: User
the question of the number of towers is the starting point of our learning Dynamic programming: Digital Triangles (POJ1163)

  * * Look for a path from the top to the bottom in the number triangle above, making the sum of the numbers on the path the largest.
  each step on the path can only go down to the bottom left or right. Just ask for this maximum and can, do not have to give a specific path. 
  the number of rows in the triangle is greater than 1 is less than or equal to 100 and the number is 0-99.
input Format:
    5      //Indicates the number of lines of the triangle.    input Triangles
    7
    3   8
    8   1   0
    2   7   4   4
    4   5   2   6   5
    require maximum output and * *
Next, let's analyze the problem-solving idea:

First, a two-dimensional array must be used to hold the number triangle;
Then we use D (R, J) to denote the J number of line R (R,j starting from 1);
We use Maxsum (R, J) to represent the sum of the numbers of the best paths in each of the paths from D (r,j) to the right side.
As a result, the final question of this question becomes the maxsum.
When we see this topic, the first thing that comes to mind is that we can solve it with a simple recursive return:
D (R, J), the next step is only D (R+1,J) or D (r+1, j+1). Therefore, for the N-line triangle, we can write the following recursive formula:

if (r = = N)                
    maxsum (r,j) = D (r,j)  
Else      
    
based on this simple recursive formula, we can easily write the full recursive code:
#include <iostream>  
#include <algorithm> 
#define MAX 101  
using namespace std; 
int D[max][max];  
int n;  
int maxsum (int i, int j) {    
    if (i==n)  
        return d[i][j];    
    int x = Maxsum (i+1,j);    
    int y = maxsum (i+1,j+1);    
    return Max (x, y) +d[i][j];  
}
int main () {    
    int i,j;    
    CIN >> N;    
    for (i=1;i<=n;i++) for   
        (j=1;j<=i;j++)        
            cin >> D[i][j];    
    cout << maxsum () << Endl;  
}      
for this recursive code, when I submit to POJ, the following results are displayed:

Yes, the code runs out of time and why does it time out. The answer is simple, because we have repeated calculations, and when we are doing recursion, the process of computing the computer helps us figure out the following:

take the third line number 1, when we calculate the number 3 starting from the 2nd row of the maxsum will be calculated from the beginning of the 1 maxsum, when we calculate from the second row of the number 8 maxsum the beginning of the time will calculate a maxsum from 1, That is, there are repeated calculations. This wastes a lot of time. This means that if a recursive method is used to traverse each path in depth, there is a large number of repeated computations. The time complexity is 2 of the N-square, for n = 100 rows, must be timed out. Next, we'll consider how to make improvements, and it's natural to think that if you save each maxsum (R,J), you can eliminate the need for duplicate calculations when you use the value next time. Then the time complexity of n-side can be used to complete the calculation. Because the total number of triangles is n (n+1)/2 based on this idea, we can improve the above code to make it a memory recursive dynamic planner:

#include <iostream>  
#include <algorithm> 
using namespace std;

#define MAX 101

int D[max][max];    
int n;  
int Maxsum[max][max];

int maxsum (int i, int j) {      
    if (maxsum[i][j]! =-1)         
        return maxsum[i][j];      
    if (i==n)   
        maxsum[i][j] = d[i][j];     
    else{    
        int x = maxsum (i+1,j);       
        int y = maxsum (i+1,j+1);       
        MAXSUM[I][J] = max (x, y) + d[i][j];     
    }     
    return maxsum[i][j]; 
} 
int main () {    
    int i,j;    
    CIN >> N;    
    for (i=1;i<=n;i++) for   
        (j=1;j<=i;j++) {       
            cin >> d[i][j];       
            MAXSUM[I][J] =-1;   
        }    
    cout << maxsum () << Endl; 
when we submit the code as above, the result is an AC

Although in a short period of time on AC. However, we are not satisfied with this code, because recursion always needs to use a lot of space on the stack, it is easy to cause stack overflow, we now have to consider how to convert recursion to recursive, let us step-by-step to complete the process. We first need to calculate the last line, so we can write the last line directly, as shown below:

now analyze each number of the penultimate row, now analyze the number 2,2 can be added to the last line 4, but also with the last line of 5 add, but it is obvious and 5 add to a larger point, the result is 7, we can save 7, and then analyze the number 7,7 can and the last line of 5 add, It is also possible to add up to 2 of the last line, and it is clear that the sum of 5 is greater and the result is 12, so we save the 12. etc... We can get the following picture:

then analyze the penultimate and penultimate lines in the same way, and finally analyze the first line, and we can get the following results in turn:


The above derivation process is not difficult to understand, after understanding we can write the following recursive dynamic planning program:

#include <iostream>  
#include <algorithm> 
using namespace std; 

#define MAX 101  

int D[max][max];   
int n;  
int Maxsum[max][max]; 
int main () {    
    int i,j;    
    CIN >> N;    
    for (i=1;i<=n;i++) for   
        (j=1;j<=i;j++)        
            cin >> D[i][j];   
    for (int i = 1;i <= n; + + i)     
        maxsum[n][i] = d[n][i];   
    for (int i = n-1; i>= 1;  i) for     
        (int j = 1; J <= i; ++j)         
            maxsum[i][j] = max (maxsum[i+1][j],maxsum[i+1][j+1]) + d[i][j];    
    cout << maxsum[1][1] << Endl;  
Our code is just that, that's enough. Of course not, we can still continue to optimize, and this optimization of course is for space optimization, in fact, there is no need to use a two-dimensional maxsum array to store each maxsum (R,J), as long as from the bottom row of rows upward recursion, so long as a one-dimensional array maxsum[100] can, That is, as long as you store a row of maxsum values. the specific recursive process for space optimization is as follows:

The next step is to follow the process of the above diagram to deduce it in one step. Further consideration, we can even maxsum array can not, directly with the nth line D directly replace the maxsum can be. But the emphasis here is that while space is saved, time complexity remains the same. in the way above, we can write the following code:

#include <iostream>  
#include <algorithm> 
using namespace std; 

#define MAX 101  

int D[max][max];  
int n; 
int * MAXSUM; 

int main () {    
    int i,j;    
    CIN >> N;    
    for (i=1;i<=n;i++) for   
        (j=1;j<=i;j++)        
            cin >> D[i][j];   
    Maxsum = D[n]; Maxsum points to nth row for    
    (int i = n-1; i>= 1;  i) for     
        (int j = 1; J <= i; ++j)       
            maxsum[j] = max (maxsum[j],maxsum[j+1]) + d[i][j];    
    cout << maxsum[1] << Endl;  
}
Next, let's take a look at the summary: General conversion methods for recursive to motion rules: The recursive function has n parameters, it defines an n-dimensional array, the subscript of the array is the value range of the recursive function parameter, the value of the array element is the return value of the recursive function, so we can start from the boundary value, gradually fill the array, which is equivalent to the inverse process of calculating the value of the recursive function. General thoughts on solving the problem of dynamic regulation 1. Decompose the original problem into sub-problems

• Decompose the original problem into a number of sub-problems that are identical or similar to the original problem, except that the scale becomes smaller. Sub-problems are solved, the original problem is solved (digital triangle example).
• Once the solution to the sub-problem is found, it is saved, so each sub-problem is solved only once. 2. Determine the status

• When solving problems with dynamic programming, we tend to refer to a set of variables associated with sub-problems as a "state". A "state" corresponds to one or more sub-problems, the so-called "state" under the "value" is the "state" corresponding to the sub-problem of the solution.
• A collection of all "states" that constitute the "state space" of the problem. The size of the state space is directly related to the time complexity of solving the problem with dynamic planning. In the example of a digital triangle, there is a total of NX (N+1)/2 numbers, so there is a total of NX (N+1)/2 states in the state space of this problem. The time complexity of the whole problem is the number of States multiplied by the time it takes to calculate each state. Each "state" in a digital triangle takes only one pass, and the time it takes to calculate each state is a constant that is independent of N. 3. Determine the values of some initial states (boundary States)

In the case of "digital triangles", the initial state is the bottom number, and the value is the bottom digit value. 4. Determine the state transition equation

Define what is "state" and "value" under that state to find out how different states are migrated-that is, how to get the "value" of another "state" (recursive) from one or more known "states" of value. The migration of States can be expressed by recursive formulas, which can also be called "state transition Equations".
The state transition equation for a digital triangle:
characteristics of the problem that can be solved by the dynamic regulation

 1) The problem has the optimal substructure property.

If the optimal solution of the problem contains the solution of sub-problems is also optimal, we call this problem has the best sub-structure properties. 2) No effect.
Once the current number of status values is determined, then the evolution of the process is only related to the values of the several states, and it does not matter which method was taken before or which path evolved to the current state. 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.