Dynamic Programming (b) the optimization of the road recursive violence - the largest digital triangle path and

Title Description

Write pictures described here

Find a triangle in the above figures from the top in the end side of the path, so that the path through which the sum of the maximum numbers. Every step on the path can only lower left or lower right away. This only requires a maximum and can, do not give a specific path.
1 is greater than the number of lines of the triangle is equal to less than 100, a digital to 0--99

Input formats:

5      //表示三角形的行数    接下来输入三角形
7
3   8
8   1   0
2   7   4   4
4   5   2   6   5

Requirements and maximum output

analysis

From the start vertex, and seeking the most. Each point has two choices, lower left or lower right, lower left and lower right which large do not know, we can add the following two points seen as the new triangle, triangle, respectively, obtained lower left and lower right triangle and the maximum path , simply select the larger of the current vertex can be applied to. This is a recursive process.

f(int[] arr,int i,int j){
  return arr[i][j]+max(f(arr,i+1,j),f(arr,i+1,j+1));
}

The pseudo-code is not considering exporting recursive, exports in the last line, because this time i and j have no way to increase, then the vertex is equivalent to not continue to go down the walk, part omitted after the plus sign It can be.

Recursive Code

  /**
   * 
   * @param triangle
   *          数字三角形
   * @param i
   *          起点行号
   * @param j
   *          起点列号
   * @return 计算出的最大和
   */
  public static int maxSumUsingRecursive(int[][] triangle, int i, int j) {
    int rowIndex = triangle.length;
    if (i == rowIndex - 1) {
      return triangle[i][j];
    } else {
      return triangle[i][j]
          + Math.max(maxSumUsingRecursive(triangle, i + 1, j),
              maxSumUsingRecursive(triangle, i + 1, j + 1));
    }
  }

As for this recursive code, when I submit to POJ, it will show the following results:

Of the code running out of time, why do overtime? The answer is simple, because we are double counting. Each of the lower left vertex and lower right two imaginary triangles, two triangles overlap. When we conduct a recursive, computer help us chart calculated as follows:

Write pictures described here

Optimization 1: memorial recursive

Take the third row of numbers 1, when we calculate MaxSum start from the second row numbers 23 calculates the MaxSum 1 from the beginning, when we calculate MaxSum start from the second row of numbers 8 will calculate the time MaxSum 1 once from the beginning, that there is double counting. This will waste a lot of time. That is if recursion method, the depth of each path traversal, the presence of a large number of repeated calculations. The time complexity is the n-th power of 2, for n = 100 rows, certainly out.

Next, we will consider how to improve the improved idea is: change and can represent recursive recursive process parameters examined in this example are two representatives of the row and column numbers. We can put the results calculated in (i, j) position cached, the next directly used to use.

There are two parameters, the cache array is two-dimensional.

According to this idea, we can put the above code improvements, making memory recursive dynamic programming program:

  /**
   * 记忆型递归
   * @param triangle
   * @param i
   * @param j
   * @return
   */
  public static int maxSumUsingMemory(int[][] triangle, int i, int j, int[][] map) {
    int rowIndex = triangle.length;
    int value = triangle[i][j];
    if (i == rowIndex - 1) {
    } else {
      //缓存有值,便不递归
      int v1 = map[i + 1][j];
      if (v1 == 0) {
        v1 = maxSumUsingMemory(triangle, i + 1, j,map);
      }
      //缓存有值,便不递归
      int v2 = map[i + 1][j+1];
      if (v2 == 0) {
        v2 = maxSumUsingMemory(triangle, i + 1, j+1,map);
      }
      value = value
          + Math.max(v1, v2);
    }
    //放入缓存
    map[i][j]=value;
    return value;
  }

The time complexity is N², space complexity is N².

Recurrence

Next, viewed in the storage map cache value, a specific value is a value which is determined by the position. In this example derived i, j the maximum required to calculate the position i + 1, j and the position i + 1, j + 1 position.

Then the precisely defined dynamic programming is calculated first, in order to obtain the position dependent. In view i Up to the last row of the array, we can begin to calculate from the last row, and then calculate the penultimate line, and so on. Let us step by step to complete this process.
We first need to calculate is the last one, so you can write directly to the last line, as shown below:

Write pictures described here

Now begin to analyze every second row of the inverse of the number, you can now analyze numbers 2,2 and 4 are added the last line, the last line and can be summed 5, it is clear that to be a little larger and 5 are added, the result is 7, this time we can save up to 7, 7, 7 can then analyze the numbers and adding the last line 5, and may be the last line of the second addition, it is clear that more and 5 are added, the result is 12, Therefore, we will save them 12. And so on. . We can get the picture below:

Write pictures described here

Then by the same token analysis reciprocal of the third and fourth from the bottom line, the first line of the final analysis, we can turn the following results:

Write pictures described here

Write pictures described here

Obviously, we can use the two-dimensional dynamic programming table, but do not need the exact path of the subject, we can compress space, using a one-dimensional array can be repeatedly used, see specific codes:

  public static int maxSumUsingDp(int[][] triangle, int i, int j) {
    int rowCount = triangle.length;
    int columnCount = triangle[rowCount-1].length;
    int[] states = new int[columnCount];
    for (int k = 0; k < columnCount; k++) {
      states[k] = triangle[rowCount-1][k];
    }
    for (int row = rowCount-2; row >= 0; row--) {
      for (int col = 0; col < triangle[row].length; col++) {
        states[col] = triangle[row][col]+Math.max(states[col], states[col+1]);
      }
    }
    return states[0];
  }

to sum up

Next, we were to sum up:

Moving the gauge general recursive transformation methods:

N has a recursive function parameter changes, to define an array, the array size is an n-dimensional parameter value range, the array index value representative of the parameter combination is called, the value of the element is the value of this state.

If the status is repeatedly calculated, you can establish a secondary array to store the calculated value, when the value of a state needs to check the auxiliary array, thus reducing the number of computations.

The inverse recursive process, consider the formation of an auxiliary array cache values. Recursion is dependent layers, the movable first order calculation rules are defined to be dependent on values ​​calculated. Starting boundary value, gradually filling the array.

Knapsack problem is two-dimensional array, the number of items * weight of the backpack

The problem is that steel bar 2 dimensional array, the length cutting mode *

The problem is two-dimensional array of the present embodiment, i * j

These problems can follow recursive - recursion memory type - dynamic programming optimization of the road.

Published 127 original articles · won 97 Like · views 310 000 +

Guess you like

Origin blog.csdn.net/zhengwei223/article/details/78762696