POJ-1836-Alignment-双向LIS(最长上升子序列)(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

题意:
  给出一列士兵的身高(会有重复),要求求出剔除最少士兵使得每一个士兵往左或者右看可以看到该队列的尽头士兵,原有的位置不得改变。
  

注意:
  1. 不能直接排序去剔除除去最高士兵以外有重复的元素,因为题目要求原来的队列顺序不变。
  2. 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.也就是说在最后得到的队列中,除了最高的那个士兵可以有重复身高之外,其他的士兵的身高不允许有重复。即最多有一个极值

思路: 

  相当于给一列数num[n],要求求删掉最少的个数,任取其中一个元素num[i],满足:1.num[0]~num[i]单调递增;2.num[i]~num[n-1]单调递减。即最多有一个极值。

  求出一个LIS一个LDS(需要倒着扫),然后从队首到队尾枚举位置,最后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

 

  

  

猜你喜欢

转载自www.cnblogs.com/OFSHK/p/11220951.html
今日推荐