动态规划:P1091 [NOIP2004 提高组] 合唱队形

P1091 [NOIP2004 提高组] 合唱队形

 

 

 

     洛谷的一题黄题,可以看得出考的是动态规划的知识点。分析题意,就是就是怎么样拿掉最少的人,使最终序列成为中间高,两边低,我们可以把这个序列看成左边是单调上升序列,右边是单调下降序列,问题就转化为从左边求每一个人的最大上升子序列,从右边求两个人的最大上升子序列,两个序列的dp1和dp2的和最大的值x,则就只要拿掉n-x个人最小,就是答案。所以我们只要从左到右和从右到左,分别用一次O(n2)的DP,求出DP1和DP2数组即可。

    上代码:

 1 //P1091 [NOIP2004 提高组] 合唱队形
 2 #include<iostream>
 3 #include<cmath>
 4 #include<algorithm>
 5 using namespace std;
 6 int a[105], dp1[105], dp2[105];
 7 int main()
 8 {
 9     int n;
10     cin >> n;
11     for (int i = 1; i <= n; ++i)cin >> a[i], dp1[i] = 1, dp2[i] = 1;//初始化为1一下
12     for (int i = 1; i <= n; ++i)//从左边计算上升序列
13         for (int j = 1; j <= i - 1; ++j)
14             if (a[i] > a[j])
15                 dp1[i] = max(dp1[j] + 1, dp1[i]);
16     for (int i = n; i >= 1; --i)
17         for (int j = n; j >= i + 1; --j)
18             if (a[i] > a[j])
19                 dp2[i] = max(dp2[j] + 1, dp2[i]);
20     int Max = -1;
21     for (int i = 1; i <= n; ++i)
22     {
23         dp1[i] += (dp2[i] - 1);//要减 因为加起来 会重复加上一个自身
24         Max = max(dp1[i], Max);
25     }
26     cout << n - Max;
27     return 0;
28 }

 

我的做法时间复杂度为O(N2),因为数据范围比较小,也能顺利通过。

这是通过图:

 

posted @ 2022-04-12 08:59  朱朱成  阅读(129)  评论(0编辑  收藏  举报