合唱队形
题目描述
N位同学站成一排,音乐老师要请其中的(N−K)位同学出列,使得剩下的K位同学排成合唱队形。
合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2,…,K,他们的身高分别为T1,T2,…,TK, 则他们的身高满足T_1<...<T_i>T_{i+1}>…>T_K(1≤i≤K)。
你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。
输入格式
共一行。
第一行是一个整数(2≤N≤100),表示同学的总数。
第二行有n个整数,用空格分隔,第i个整数Ti(130≤Ti≤230)是第ii位同学的身高(厘米)。
输出格式
一个整数,最少需要几位同学出列。
输入输出样例
输入 #1
8
186 186 150 200 160 130 197 220
输出 #1
4
分析:
此题首先可以判断出它是两个单调升序列,从开头向后,和从后向前,类似于 拦截导弹 那道题。
本题的算法是动态规划的一个好题,从下面的代码,可以看出此题的解法复合了动态规划的把大问题化成小问题来做,而且没有每次重新做已经做过的任务,类似于数据结构种的一个记录表。
代码如下:
1 #include<iostream>
2 using namespace std;
3 #include<algorithm>
4 int n,a[105],f1[105],f2[105],ans;
5 int main(){
6
7 cin>>n;
8 for(int i=1;i<=n;i++) cin>>a[i];
9 a[0]=0;
10 for(int i=1;i<=n;i++)//从1到n求最长升
11 for(int j=0;j<i;j++) {
12 // cout<<"a[j]= "<<a[j]<<" a[i]= "<<a[i]<<" f1[i] = "<<f1[i]<<endl;
13 if(a[i]>a[j])
14 f1[i]=max(f1[i],f1[j]+1);
15 }
16 a[n+1]=0;
17 cout<<endl<<endl;
18 for(int i=n;i;i--)//从n到1求最长升
19 for(int j=n+1;j>i;j--)
20 if(a[i]>a[j])
21 f2[i]=max(f2[i],f2[j]+1);
22 for(int i=1;i<=n;i++)
23 ans=max(f1[i]+f2[i]-1,ans);//枚举Ti,从1到Ti的最长升+从TK到Ti的最长升-1(Ti被加了两次)
24 cout<<n-ans<<endl;
25 return 0;
26 }
因上求缘,果上努力~~~~ 作者:图神经网络,转载请注明原文链接:https://www.cnblogs.com/BlairGrowing/p/12741921.html