Bidirectional POJ-1836-Alignment- the LIS (rising longest sequence) (LIS + LSD) + dp

In the army, a platoon is composed by n soldiers. During the morning inspection, the soldiers are aligned in a straight line in front of the captain. The captain is not satisfied with the way his soldiers are aligned; it is true that the soldiers are aligned in order by their code number: 1 , 2 , 3 , . . . , n , but they are not aligned by their height. The captain asks some soldiers to get out of the line, as the soldiers that remain in the line, without changing their places, but getting closer, to form a new line, where each soldier can see by looking lengthwise the line at least one of the line's extremity (left or right). A soldier see an extremity if there isn't any soldiers with a higher or equal height than his height between him and that extremity. 

Write a program that, knowing the height of each soldier, determines the minimum number of soldiers which have to get out of line. 

Input

On the first line of the input is written the number of the soldiers n. On the second line is written a series of n floating numbers with at most 5 digits precision and separated by a space character. The k-th number from this line represents the height of the soldier who has the code k (1 <= k <= n). 

There are some restrictions: 
• 2 <= n <= 1000 
• the height are floating numbers from the interval [0.5, 2.5] 

Output

The only line of output will contain the number of the soldiers who have to get out of the line.

Sample Input

8
1.86 1.86 1.30621 2 1.4 1 1.97 2.2

Sample Output

4 

meaning of the questions:
  given a soldier's height (will repeat), excluding the minimum requirements to obtain the soldiers so that each soldier left or right you can see the end of the queue to see the soldiers, the original position may not change.
  

note:
  1. Sort can not be directly removed to the outside excluding the highest soldiers duplicate elements, because the original subject of the request queue order unchanged.
  2. A soldier see an extremity if there is not any soldiers with a higher or equal height than his height between him and that extremity. That is last in the queue to get in, in addition to the soldier may have the highest repeat height than the other the soldier's height does not allow duplicate. That is a maximum of one extreme

 

Ideas: 

  Is equivalent to the number num [n] a required minimum number required to delete, take any one of the elements [i] num, satisfy: 1.num [0] ~ num [i] monotonically increasing; 2.num [i ] ~ num [n-1] monotonically decreasing. That is up to one extreme.

  Obtaining a LIS a the LDS (backwards sweep required) , and then from the tail to the head of the queue enumeration position, and finally ans = n-max (dp1 [ i] + dp2 [i]).

 

 原数据:1.86  1.86  1.30621  2  1.4  1  1.97  2.2
 最长上升子序列:1.86
         1.30621 2
        1.30621 1.4 (1.4去替换掉了2的位置)
         1 1.4 1.97 2.2 (1比1.30621更优,去替换掉了1.30621的位置,而后面的数据不需要更新)(最后凭借这个序列求出最长长度,这个的最长长度是和正确排序得出的长度是一样的)
        (1.30621 1.4 1.97 2.2 )(而这个长度与上面那一组数据长度一样,这个是正确排序的长度)
         最长长度:4
 最长下降子序列:1.86 1.30621
         2 1.30621
         2 1.4
         2 1.4 1
         2 1.97 1
         2.2 1.97 1
         (1.86 1.30621 1;1.86 1.4 1;2 1.4 1)
         最长长度:3
需要注意的是:求出来的只是序列的最长上升或下降长度,但是里面的元素不一定是按照上升或者下降的顺序进行排好的,只是用一个更优的数据去替换掉了原有的数据的位置。)

针对该题时间复杂度问题:对于最长上升子序列问题有两种写法,正常写O(n2),怕超时可以用O(nlogn)的写法。


 

 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<string.h>
 4 #include<algorithm>
 5 #define inf 0x3f3f3f3f
 6 using namespace std;
 7 
 8 float a[1010];
 9 int dpup[1010];
10 int dpdown[1010];
11 
12 int main()
13 {
14     std::ios::sync_with_stdio(false);
15     int n;
16     cin>>n;
17     memset(dpup,0,sizeof(dpup));
18     memset(dpdown,0,sizeof(dpdown));
19     for(int i=0; i<n; i++)
20         cin>>a[i];
21     for(int i=0; i<n; i++)
22     {
23         dpup[i]=1;
24         for(int j=0; j<i; j++)
25         {
26             if(a[j]<a[i])
27             {
28                 dpup[i]=max(dpup[i],dpup[j]+1);
29             }
30         }
31     }
32 //
33 //    for(int i=0; i<n; i++)
34 //    {
35 //        dpdown[i]=1;
36 //        for(int j=0; j<i; j++)
37 //        {
38 //            if(a[j]>a[i])
39 //            {
40 //                dpdown[i]=max(dpdown[i],dpdown[j]+1);
41 //            }
42 //        }
43 //    }
44 
45     for(int i=n-1; i>=0; i--) //这里需要倒着扫
46     {
47         dpdown[i]=1;
48         for(int j=n-1; j>i; j--)
49         {
50             if(a[i]>a[j])
51                 dpdown[i]=max(dpdown[j]+1,dpdown[i]);
52         }
53     }
54     int ans=-inf;
55     for(int i=0; i<n; i++)
56     {
57         for(int j=i+1; j<n; j++)
58         {
59             //      if(a[i]==a[j])
60             //         ans=max(ans,dpup[i]+dpdown[j]-1);
61             //      else
62             ans=max(ans,dpup[i]+dpdown[j]);
63         }
64     }
65     cout<<n-ans<<endl;
66     return 0;
67 }
View Code

 

 

 

  

  

Guess you like

Origin www.cnblogs.com/OFSHK/p/11220951.html