Since we have already mentioned the longest common subsequence, we will also talk about this incremental subsequence. In the same way, subsequence indicates that such subsequences are not consecutive. For example, there are subsequences {1, 9, 3, 8, 11, 4, 5, 6, 4, 19, 7, 1, 7} the longest incrementing subsequence of such a string is {1, 3, 4, 5, 6, 7} or {1, 3, 4, 5, 6, 19 }.

In fact, this problem is related to the longest common subsequence problem. Assume our initial sequence S1. Then we should sort them from small to large first. Get S1 '. In this way, we can know the answer through the longest common subsequences of S1 and s1': is it a bit clever. This process is quite intuitive. However, this is not the focus of this Article. There are more traditional approaches to this issue.

We define L (j) as an optimized sub-structure, that is, the longest incrementing sub-sequence. Then the relationship between L (j) and L (1 .. J-1) can be described

**L (j) = max {L (I), I <J & AI <AJ} + 1**That is to say, L (j) is equal to the largest L (I) plus one of all the preceding L (I. such L (I) must meet the condition that AI <AJ. this inference is easy to understand. that is, all the values before J must be smaller than the maximum value of the current array.

We can easily write the following code:

// Longest_increase_subsequence.cpp: defines the entry point for the console application. <br/> // <br/> # include "stdafx. H "<br/> # include <vector> <br/> # include <iostream> <br/> # include" windows. H "<br/>/** <br/> * Description: calulate the longest increase subsequence <br/> * @ Param S1, source sequence <br/> * @ Param S2, output, longest increase sequence <br/> */<br/> template <typename T> void longest_increase_subsequence (const STD :: vector <t> & S1, STD: vector <t> & S2) <br/>{</P> <p> int n = s1.size (); if (n <1) return; <br/> int m = 0; <br/> int K = 0; <br/> STD :: vector <unsigned int> B (n + 1, 1); <br/> STD: vector <unsigned int> P (n + 1, 0 ); </P> <p> for (INT I = 1; I <= N; I ++) <br/> {<br/> for (Int J = 1; j <I; j ++) <br/> {<br/> If (S1 [I-1]> S1 [J-1] & B [I] <B [J] + 1) <br/>{< br/> B [I] = B [J] + 1; <br/> P [I] = J; <br/>}< br/> for (INT I = 1; I <= N; I ++) <br/>{< br/> If (M <B [I]) <br/>{< br/> M = B [I]; <br/> K = I; <br/>}< br/> s2.resize (m); <br/> while (k> 0) <br/>{< br/> S2 [M-1] = S1 [k-1]; <br/> m --; <br/> K = P [k]; <br/>}< br/> int _ tmain (INT argc, _ tchar * argv []) <br/> {<br/> int A [] = {1, 9, 3, 8, 11, 4, 5, 6, 4, 19, 7, 1, 7 };< br/> STD: vector <int> seq (A, A + sizeof (a)/sizeof (A [0]); <br/> STD:: vector <int> r; <br/> longest_increase_subsequence (SEQ, R); <br/> for (INT I = 0; I <R. size (); I ++) <br/> STD: cout <R [I] <""; <br/> STD: cout <STD :: endl; <br/> system ("pause"); <br/> return 0; <br/>}

Similar to the previous Code, here are some secondary two-dimensional array P used to trace the longest subsequence. the time complexity of the entire algorithm reaches O (n Limit 2 ). of course there are some nlog (n) implementations. but it is not the focus of dynamic planning.

We can focus on the expansion of this issue. The following two problems are also classic issues.

Question 1: The original question of bridge construction is as follows:**Building bridges.**Consider a 2-D map with

Horizontal river passing through its center. There are n cities on

The southern bank with X-coordinates A (1)... a (n) and N cities

On the northern bank with X-coordinates B (1)... B (n). You want

To connect as usual North-South pairs of cities as possible

Bridges such that no two bridges cross. When connecting cities, you

Can only connect city I on the northern bank to city I on the southern

Bank. (Note: this problem was incorrectly stated on the paper copies

Of the handout given in recitation .)

It is generally necessary to build several bridges between cities on the north and south sides of a river. the cities on both sides of the bridge are A (1 )... A (n) and B (1 )... B (n ). the requirement here is that a (I) can only build a bridge with B (I), and the two bridges cannot cross each other. we hope we can get a solution with as many bridges as possible.

For example, in the figure above, it seems that some people have no idea at first, but after careful consideration, this is actually a perfect deformation of the question of the longest public subsequence. How can we say this? If you sort City A on the Henan side, you can get a sequence. for example, here S1 = {, 4} is obtained, and the North is also sorted in order to obtain the sequence S2 = {, 3 }. the index in the north sequence is calculated from the first bridge in the south. that is, the position of each value in S1 relative to S2. for example, A2 is the first in the south and the second in the north, so the first element is 2. the corresponding location of A1 in the north is 1. a3 corresponds to 5 in the north, A5 corresponds to 3 in the north, and the last A4 corresponds to 3 in the north. in this way, we get a new sequence S3 = {2, 1, 5, 3, 4 }. the actual significance of this sequence is that the first bridge in the South needs to be connected to the second bridge in the north. the ideal situation is incremental, so that all the bridges can be built :) That is to say, our bridge building problem is transformed into the problem of finding the longest ascending subsequence of this sequence. of course {1, 3, 4 }. that is, the bridge represented by the red line.

The code is not pasted, but the problem is indeed quite mysterious.

Question 2.**Box stacking**. You are given a set of N types

Rectangular 3-D boxes, where the I ^ th box has height H (I), width

W (I) and depth d (I) (all real numbers). you want to create a stack

Of boxes which is as tall as possible, but you can only stack a box on

Top of another box if the dimensions of the 2-D base of the lower box

Are each strictly larger than those of the 2-D base of the higher box.

Of course, you can rotate a box so that any side functions as its

Base. It is also allowable to use multiple instances of the same

Type of box.

A brief description of this problem is that there are several different boxes. you need to stack it as high as possible. however, the box must be placed in the following and smaller ways. the box can be rotated and the quantity is not limited. A set of boxes is required to obtain the maximum height that can be placed. in fact, this problem is also the longest incremental subsequence problem. it's just a bit more hidden. because the box can be flipped. first, we define the long, wide, and high boxes as H, W, and D. to avoid repeated computation, we agree W <= D. in this way, each box can be changed to three boxes. in this way, we don't have to consider the rotation issue. step 1: sort the boxes by W * D. (You can think about how to sort social media ). then our model began to use H (j) to represent the height of the box when the J box was created. rememberThe longest incrementing subsequenceThe constraint is that AI <AJ. Here the condition is changed to the corresponding di <DJ & wi <WJ. At the same time, the original + 1 is changed to + hi.

The last part of the post is not very good code, but it is still working:

// Box_stacking.cpp: defines the entry point for the console application. <br/> // <br/> # include "stdafx. H "<br/> # include <iostream> <br/> # include <vector> <br/> # include <algorithm> <br/> # include <functional> <br /> # include "windows. H "<br/>/* <br/> box stacking. you are given a set of N types of rectangular 3-D boxes, <br/> where the I ^ th box has height H (I), width W (I) and depth d (I) (all real numbe RS ). <br/> you want to create a stack of boxes which is as tall as possible, <br/> but you can only stack a box on top of another box if the dimensions of the 2-D base of <br/> the lower box are each strictly larger than those of the 2-D base of the higher box. <br/> Of course, you can rotate a box so that any side functions as its base. <br/> it is also allowable to use multiple instances of the same Type of box. <br/> */<br/> struct box <br/> {<br/> int h; // height; <br/> int W; // width; <br/> int D; // depth; <br/>}; <br/> struct sizesort: public STD: binary_function <box, box, bool> <br/> {<br/> bool operator () (const box & B1, const box & B2) <br/>{< br/> return b1.w * b1.d> b2.w * b2.d; <br/>}< br/>}; <br/> int highest_box_stacking (const STD :: vector <Box> & B) <br/> {<br/> // first make the box 1*2*3 <B R/> // to like this: 1 * (2*3), 2 * (1*3), 3*(1*2 ); <br/> // Let's assume width <= depth, then we can get 3 * n boxes. <br/> If (B. size () <1) <br/> return 0; <br/> STD: vector <Box> box (B. size () * 3); <br/> for (INT I = 0; I <B. size (); I ++) <br/>{< br/> box [I * 3 + 0]. H = B [I]. h; <br/> box [I * 3 + 0]. W = B [I]. W <B [I]. d? B [I]. w: B [I]. d; <br/> box [I * 3 + 0]. D = B [I]. W <B [I]. d? B [I]. d: B [I]. w; <br/> box [I * 3 + 1]. H = B [I]. w; <br/> box [I * 3 + 1]. W = B [I]. h <B [I]. d? B [I]. h: B [I]. d; <br/> box [I * 3 + 1]. D = B [I]. h <B [I]. d? B [I]. d: B [I]. h; <br/> box [I * 3 + 2]. H = B [I]. d; <br/> box [I * 3 + 2]. W = B [I]. h <B [I]. w? B [I]. h: B [I]. w; <br/> box [I * 3 + 2]. D = B [I]. h <B [I]. w? B [I]. w: B [I]. h; <br/>}< br/> STD: Sort (box. begin (), box. end (), sizesort (); </P> <p> STD: vector <int> M (B. size () * 3); <br/> M [0] = Box [0]. h; <br/> for (INT I = 1; I <box. size (); I ++) <br/>{< br/> for (Int J = 0; j <I; j ++) <br/> {<br/> If (Box [I]. W <= Box [J]. w) & (Box [I]. d <= Box [J]. d) & (M [I] <m [J] + box [I]. h) <br/> M [I] = m [J] + box [I]. h; <br/>}< br/> return * STD: max_element (M. begin (), M. end (); <br/>}< br/> int _ tmain (INT argc, _ tchar * argv []) <br/>{< br/> STD :: vector <Box> box (3); <br/> box [0]. H = 2; <br/> box [0]. W = 3; <br/> box [0]. D = 4; <br/> box [1]. H = 2; <br/> box [1]. W = 3; <br/> box [1]. D = 1; <br/> box [2]. H = 5; <br/> box [2]. W = 3; <br/> box [2]. D = 4; <br/> STD: cout <pighest_box_stacking (box) <STD: Endl; <br/> system ("pause "); <br/> return 0; <br/>}< br/>

So far, I still feel that there is no shortcut to learning dynamic planning, that is, to try different types of problems and classify these problems through analysis. as a result, when a new problem occurs, we try our best to set up a known problem. We hope that we can use a known solution to solve the unknown problem.