Application summary and Code Implementation of Dynamic Planning Algorithms

Source: Internet
Author: User
Document directory
  • 1.1.1 step jumping Problem
  • 1.1.2 maximum and subsequence
  • 1.1.3 Joseph Ring
  • 1.2.1 longest ascending/descending subsequence (LIS, LDS)
  • 1.2.3 edited distance)
  • 1.2.4 backpack Problems
  • 1.3.2 Short Circuit
Reprinted please indicate the source:

Http://blog.csdn.net/xiaohongsimon/article/details/10264735
Dynamic Programming)

An English explanation of dynamic planning is in place: whenever the results of subproblems are needed, they have alreadybeen computed, and can be simply be looked up in a table. That is, the computation of all subproblems can be completed by the query table. The advantage of dynamic planning is to avoid repeated computation of subproblems as much as possible.

1.1 O (n) Problems

The complexity of the O (n) DP can generally be abstracted as F (n) problem, remember the High School Series question, "known F (n) = 2f (N-1 ), F (0) = 1, find the leading expression of F (N), isn't it easy? However, actual problems often require us to discover this recursive relationship by ourselves, so as to simplify complicated problems.

1.1.1 step jumping Problem

A step has a total of N levels. If you can skip 1 level at a time, you can also skip 2 levels. Calculate the total number of hops in total and analyze the time complexity of the algorithm.

Think of the jump Method for n-level steps as a n function and mark it as F (n ). When N> 2, there are two different options for the first hop: one is the first hop with only one level. At this time, the number of hops equals to the number of hops for the next n-1 level step, that is F (n-1); another option is the first jump level 2, at this time the number of Jump method is equal to the number of the next step of the N-2 level, that is, F (n-2 ). Therefore, F (n) = f (n-1) + (F-2) of different hops at N-level steps ).

1.1.1.1 Recursive Method

From this analysis, I believe many people can see that this is the familiar sequence of fiber ACCI. Directly recursive solving involves a lot of repeated computations. We use solving F (10) as an example to analyze the recursive solving process. F (10) and F (9) and F (8) are required ). Similarly, if F (9) is required, F (8) and F (7)… must be obtained first )......

Before analyzing its complexity, we can intuitively look at the test time curve:

#encoding=utf8 def Fibonacci(n):    if n == 1 or n ==0:        return 1return Fibonacci(n-1)+Fibonacci(n-2)

Implementation/length

10

20

30

40

Recursion

4.69e-05

0.0046

0.5660

69.8280

 

I was surprised to see this result, but the length was not over a hundred times. It took me some time to reach an intolerable level. To better understand the complexity, let's draw a picture:

 

At first glance, I thought it was a linear relationship, right? The ordinate is log10. That is to say, recursion solves this problem. The time complexity is exponential. So how is this exponential level derived?

Only from the recursive formula, N each plus 1, the calculation time is approximately increased to two times (if F (n) = 2f (N-1), then it is easy to see O (N) = 2 ^ N). In fact, the complexity is O (1.618 ^ N). For details, refer to some feature value calculation methods.

1.1.1.2 Dynamic Planning

def Fibonacci_dp(n):    res = [1]*(n+1)    if n == 1 or n ==0:        return 1    for i in range(2,n+1):        res[i]= res[i-1]+ res[i-2]return res[n]

 

Implementation/length

10

20

30

40

Recursion

4.69e-05

0.0046

0.5660

69.8280

DP

1.09e-05

9.05e-06

9.06e-06

1.09e-05

Obviously, the time complexity of DP is O (n), and it only requires a fixed physical space overhead. The reason why this problem is classified as one-dimensional DP, it also requires a one-dimensional secondary array res [n + 1].

In comparison, the performance improvement is very obvious.

1.1.1.3 Matrix Solution

This problem still involves the solution of logn, but it has nothing to do with our DP topic. Please try again later.

1.1.2 maximum and subsequence

Enter an integer array lst []. The array also has a positive number and a negative number. One or more consecutive integers in the array form a sub-array. Each sub-array has a sum. Calculate the maximum value of the sum of all sub-arrays and the sub-array. The time complexity is O (n ).

1.1.2.1 problem Abstraction:

F (n) indicates the sequence 0, 1 ,... The largest sum of N, that is, F (n) represents the largest sum of the array ending with lst [N.

1.1.2.2 recurrence relationship:

F (n) = max (0, F (n-1) + lst (n )).

Example:

LST []: [-5, 7,-2,-6, 5,-1, 4]

F []: [0, 7, 5, 0, 5, 4, 8]

The maximum value of F is 8, which is our final requirement. Start tracing from this position and always encounter a zero position. This interval is the largest and subsequence. Time complexity O (N) and space complexity O (n ).

 

def max_subsum(lst):    n = len(lst)    f = [0]*n    f[0]= max(lst[0],0)    for i in range(1,n):        f[i]= max(0,f[i-1]+lst[i])    idx_max = f.index(max(f))    idx_min = idx_max    while idx_min>=0and f[idx_min]> 0:        idx_min -=1return lst[idx_min+1:idx_max+1]

1.1.2.3 maximum submatrix

This is actually a kind of deformation of the "maximum sub-array" problem, but the one-dimensional problem is converted into a two-dimensional problem. Of course, the solution is to convert the two-dimensional problem into one-dimensional.

First, traverse the child matrix A [I] [N], I = 1, 2 ,... N, all columns are added to obtain a one-dimensional array, and then converted to the maximum sub-array. complexity O (N ^ 3 ).

There is a solution called the "hanging line method" on the Internet (talking about how to solve the largest subrectangle problem with a very big idea, Wang zhikun). This problem can be solved within n ^ 2, I have the opportunity to add more information.

1.1.3 Joseph Ring

Problem description: N count, 0 ~ N-1, 0 is used as the 1st number, and the M number is deleted. The next number of the deleted number is used as the first number in the next round. Delete the number until the next number is left, evaluate the subscript of this number in the original sequence.

Analysis:

F (n, m) indicates n people, according to the rule, the subscript of the remaining person. The first subscript of the number to be deleted is s-1. Then M becomes the beginning of the next round (f (n-1, M), and m + 1 becomes 1...

Subscript of F (n, m)

After adjustment

Subscript for F (n-1, m)

0

M

0

1

M + 1

1

...

M + 2

2

M-1 (to be deleted)

...

...

M

N-2

N-m-2

M + 1

N-1

N-m-1

...

0

N-m

N-2

1...

N-(m-1 )...

N-1

M-2

N-2

It is not difficult to find that if the subscript of the last number in F (n-1, m) is X, then it is in F (n, m) the subscript in is (x + M) % N, and the subscript of the last number must be 0, so we can use DP to evaluate

In comparison, this question is more entertaining and not widely used.

1.2 O (N ^ 2) problem 1.2.1 longest ascending/descending subsequence (LIS, LDS)

Given a sequence of A1, A2,... an, without changing the relative order, find its largest subset to meet the requirement that any I <J has AI <AJ

Problem Abstraction:

F [k] indicates the maximum Lis length ending with an AK

Recurrence relationship:

F [k] = max (F [I]) + 1, I <K & AI <AK

 

def lis_n2(seq):    n = len(seq)    if n <=0 :        return 0    e =  [1]* n       #e[i] is thelength of sub lis which end with seq[i]    step = [-1]* n    #step[i] is predecessor of the sub seq.ending at seq[i]    for i in range(1,n):        _max = 0        for j in range(i):            if seq[i]> seq[j]and e[j]>_max:               _max = e[j]               step[i]= j        e[i]= _max+1      # e[i] = max( e[j]) + 1, j= 0...i-1 and seq[i]>seq[j]     # max(e) is thelength of lis    # further we getthe lis more than its length     res = []    idx = e.index(max(e))    while(idx!= -1):        res += [seq[idx]]        idx = step[idx]    res = res[::-1] # reverse    return res

 

1.2.2 Longest Common subsequence (longest common subsequence) 1.2.2.1 Problem Description

Specify two sequences (arrays or strings in C and List in Python) and find the largest common subsequences of the two. The relative sequence of elements in the subsequence remains unchanged and is not necessarily continuous. For example, in "abcdef", "ABC" and "Ace" are counted as subsequences. Of course, it is not difficult to draw a conclusion, a sequence with a length of N with a sub-sequence composition of 2 ^ N (back to arrange the combination)

1.2.2.2 Recursion

The exponential complexity problem often cannot be solved in one step (it is unacceptable to make a direct effort). Therefore, we should consider whether we can solve its subproblems through a roundabout approach. For the two sequences X, Y, whose lengths are n, m, we can find that the LCS results of X and Y can be obtained from one of the three sub-problems:

1. LCS (x1. .. n-1, y1. .. m)

2. LCS (x1. .. n, y1. m-1)

3. LCS (x1. .. n-1, y1. m-1) + public tail Element

 

def lcs_len(x, y):   """This function returns length of longest commonsequence of x and y."""      if len(x)== 0 or len(y)== 0:        return 0       if x[-2]== y[-2]: # if last but one elements of x and y areequal        return lcs_len(x[:-1], y[:-1])+ 1    else:        return max(lcs_len(x[:-1], y), lcs_len(x, y[:-1]))

1.2.2.3 dynamic planning O (N ^ 2)

Apparently, recursive operations introduce many repeated computations. Dynamic Planning can solve this problem. One of its English explanations is very good: whenever the results of subproblems are needed, they have alreadybeen computed, and can simply be looked up in a table. That is, the calculation of all sub-problems can be completed by the table! Let's take a look at the Code:

 

def lcs_dp(x, y):    n = len(x)    m = len(y)    table = dict() # a hashtable, but we'll use it as a 2Darray here       for i in range(n+1):    # i=0,1,...,n        for j in range(m+1): # j=0,1,...,m            if i== 0or j ==0:               table[i, j]= 0            elif x[i-1]== y[j-1]:               table[i, j]= table[i-1, j-1]+ 1            else:               table[i, j]= max(table[i-1, j], table[i, j-1])                               # Now, table[n, m]is the length of LCS of x and y.                               # Let's go onestep further and reconstruct                # the actualsequence from DP table:                   def recon(i, j):        if i == 0 or j ==0:            return""        elif x[i-1]== y[j-1]:            return recon(i-1, j-1)+ str(x[i-1])        elif table[i-1, j] > table[i, j-1]:            return recon(i-1, j)        else:            return recon(i, j-1)           return recon(n, m)

A 2D table is used in the code, and table (I, j) represents the lcs_len Of The subproblem (I, j). After analysis, its value may only be a table (I-1, j-1), table (I, J-1), table (I-1, j) One, so from top to bottom, from left to right assignment does not appear table (I, j) the assignment is not possible. Of course, obtaining lcs_len is not our ultimate goal, especially in applications. Generally, we need to obtain this LCS, so we can obtain the result through table (see the code ).

1.2.2.4 rolling array-space optimization

The process of solving this problem can be seen as the process of filling the matrix table from top to bottom, from left to right, so its time and space complexity is O (n ^ 2 ). If time complexity is still mentioned, the space complexity cannot be tolerated. The stack space of a process is about several Mb, imagine n = 1024 (this length is not too long). If each element has 4 bytes, the matrix consumes 4 MB of stack space. If such a function is used in a system, it is very dangerous to implement other functions, which may cause system crash. So how to optimize it?

In fact, in the calculation process, table [I, j] only depends on three values: Table [I-1, J-1], table [I-, J] Table [I, J-1], therefore, we only need two layers of table [2] [N]. When we want to read and write data to row I, we only need to use the subscript I % 2. In this way, the space complexity is reduced to O (n)

def lcs_dp_v1(x, y):    n = len(x)    m = len(y)    table = dict() # a hashtable, but we'll use it as a 2Darray here       for i in range(n+1):    # i=0,1,...,n        for j in range(m+1): # j=0,1,...,m            if i== 0or j ==0:               table[i%2, j]= 0            elif x[(i-1+2)%2]== y[j-1]:                table[i, j]= table[(i-1+2)%2, j-1]+ 1            else:               table[i, j]= max(table[(i-1+2)%2, j], table[i, j-1])    return table[n%2,m]

One detail in the code should be noted that it is very dangerous to take (I-1) % 2 directly, so it needs to be converted to (I-1 + 2) % 2 for protection.

1.2.3 edited distance 1.2.3.1 Problem Description

The distance between two strings is equal to (1) Insert, (2) Delete, (3) replace, or (4) convert a string into another string) the minimum number of operations performed on adjacent character exchanges.

1.2.3.2 recursive relationship

1. if I = 0 or J = 0:

Ed [I] [J] = max (I, j)

2. If I <= 1 or j <= 1:

Ed [I] [J] = min (edit (I-1, j) + 1, edit (I, J-1) + 1, edit (I-1, J-1) + f (I, j ))

3. If I> = 2 and j> = 2 and S1 [I-1] = S2 [J-2] ands1 [I-2] = S2 [J-1]:

Ed [I] [J] = min (edit (I-1, j) + 1, edit (I, J-1) + 1, edit (I-1, J-1) + f (I, j), edit (I-2, J-2) + 1)

At first glance, it is a bit complicated. In fact, its idea is similar to LCS. The process is to fill a two-dimensional matrix, but here we need to save three layers of data.

1.2.3.3 O (N ^ 2) Implementation

def edited_distance(s1,s2):    mat = {}    for i in range(0,len(s1)+1):        for j in range(0,len(s2)+1):            if i==0or j==0:                mat[i,j]= i+j                continue            mat[i,j]= mat[i-1,j-1]+ int(s1[i-1]!=s2[j-1])            if mat[i,j]> mat[i-1,j]+1:                mat[i,j]= mat[i-1,j]+1            if mat[i,j]> mat[i,j-1]+1:                mat[i,j]= mat[i,j-1]+1            if i>=2and j>=2and s1[i-2]==s2[j-1]and s1[i-1]==s2[j-2]and mat[i,j]>mat[i-2,j-2]+1:                mat[i,j]= mat[i-2,j-2]+1    return mat[len(s1),len(s2)]

1.2.3.4 Optimization

First, the space can be optimized according to the rolling array mentioned in LCS. Second, there is an implicit problem in the editing distance, that is, in generating a two-dimensional matrix, an element must be smaller than the element in the lower right corner of the adjacent table. The specific derivation is skipped. As for its usefulness, if we want to implement a search based on a certain threshold (for example, if the editing distance exceeds 5, we do not need to calculate it again), it will accelerate a lot of time.

The following code provides space optimization:

def edited_distance_v1(s1,s2):    mat = {}     s1 = s1.decode("utf8")    s2 = s2.decode("utf8")    for i in range(0,len(s1)+1):        for j in range(0,len(s2)+1):            if i==0 or j==0:                mat[i%3,j] = i+j                continue            mat[i%3,j] = mat[(i-1+3)%3,j-1] + int(s1[i-1]!=s2[j-1])            if mat[i%3,j] > mat[(i-1+3)%3,j]+1:                mat[i%3,j] = mat[(i-1+3)%3,j]+1            if mat[i%3,j] > mat[i%3,j-1]+1:                mat[i%3,j] = mat[i%3,j-1]+1            if i>=2 and j>=2 and s1[(i-2+3)%3]==s2[j-1] and s1[i-1]==s2[j-2] and mat[i%3,j]>mat[(i-2+3)%3,j-2]+1:                mat[i%3,j] = mat[(i-2+3)%3,j-2]+1    return mat[len(s1)%3,len(s2)]
1.2.4 backpack problem 1.2.4.1 Problem Description

This is a complete NP problem for combined optimization. The problem can be described as: Given a group of items, each item has its own weight and price. Within the limited total weight, how can we choose to make the total price of the item the highest.

1.2.4.2 recursive relationship

Among them, DP [I, j] indicates the maximum value that can be generated when the previous I items are loaded into a backpack with a capacity of J:

If (W [I]> J)

DP [I, j] = DP [I-1, J]

Else

DP [I, j] = max (DP [I-1, J-W [I] + V [I], DP [I-1, J]) // whether or not I is required

 

1.3 O (N ^ 3) problem 1.3.1 Post Office site selection 1.3.1.1 Problem Description

There are some villages (in a straight line) around a street, and some post offices need to be set up in these villages (at most one in a village ), the minimum distance from each village to the nearest post office.

1.3.1.2 recurrence relationship:

State transition equation: DP [I] [J] indicates the optimal solution of the first post office in the first J villages.

DP [I] [J] = min (DP [I-1] [k] + cost [k + 1] [J]) I-1 = <k <= J-1

# Include <stdio. h> int V, p; int position [310]; int getcost (int I, Int J) // create a minimum post office path and {int sum = 0 between village I and j; while (I <j) {sum + = (position [j --]-position [I ++]);} return sum;} int main (){... For (j = 1; j <= V; j ++) DP [1] [J] = getcost (1, J); for (I = 2; I <= P; I ++) {for (j = I; j <= V; j ++) {minsum = 0x7fffffff; For (k = I-1; k <= J-1; k ++) {minsum = (minsum> DP [I-1] [k] + getcost (k + 1, J ))? DP [I-1] [k] + getcost (k + 1, J): minsum;} DP [I] [J] = minsum ;}} printf ("% d ", DP [p] [v]); Return 0 ;}

1.3.2 Short Circuit

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.