这是以前写的==转过来qwq
【例8】合唱队形
【问题描述】
N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形。
合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1, 2, …, K,他们的身高分别为T1, T2, …, TK,则他们的身高满足T1 < T2 < … < Ti , Ti > Ti+1 > … > TK (1≤i≤K)。
你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。
【输入文件】
输入文件chorus.in的第一行是一个整数N(2 ≤ N ≤ 100),表示同学的总数。第二行有n个整数,用空格分隔,第i个整数Ti(130 ≤ Ti ≤ 230)是第i位同学的身高(厘米)。
【输出文件】
输出文件chorus.out包括一行,这一行只包含一个整数,就是最少需要几位同学出列。
【样例输入】
8
186 186 150 200 160 130 197 220
【样例输出】
4
【数据规模】
对于50%的数据,保证有n ≤ 20;对于全部的数据,保证有n≤100。
【算法分析】
我们按照由左而右和由右而左的顺序,将n个同学的身高排成数列。如何分别在这两个数列中寻求递增的、未必连续的最长子序列,就成为问题的关键。设
a 为身高序列,其中a[i]为同学i的身高;
b 为由左而右身高递增的人数序列,其中 b[i]为同学1‥同学i间(包括同学i)身高满足递增顺序的最多人数。显然b[i]={b[j]|同学j的身高<同学i的身高}+1;
c为由右而左身高递增的人数序列,其中c[i]为同学n‥同学i间(包括同学i)身高满足递增顺序的最多人数。显然c[i]={c[j]|同学j的身高<同学i的身高}+1;
由上述状态转移方程可知,计算合唱队形的问题具备了最优子结构性质(要使b[i]和c[i]最大,子问题的解b[j]和c[k]必须最大(1≤j≤i-1 ,i+1≤k≤n))和重迭子问题的性质(为求得b[i]和c[i],必须一一查阅子问题的解b[1]‥b[i-1]和c[i+1]‥c[n]),因此可采用动态程序设计的方法求解。
显然,合唱队的人数为(公式中同学i被重复计算,因此减1),n减去合唱队人数即为解。
【AC】
1 #include<iostream>
2
3 #include<cstdio>
4
5 using namespace std;
6
7 int a[500],b[500],c[500],i,j,n,m;
8
9 int main()
10
11 {
12
13 scanf("%d",&n);
14
15 for(i=1; i<=n; i++)
16
17 cin>>a[i];
18
19 for(i=1; i<=n; i++)
20
21 {
22
23 c[i]=1;
24
25 for(j=1; j<=i-1; j++)
26
27 if((a[j]<a[i])&&(c[j]+1>c[i]))
28
29 c[i]=c[j]+1;
30
31 }
32
33 for(i=n; i>=1; i--)
34
35 {
36
37 b[i]=1;
38
39 for(j=i+1; j<=n; j++)
40
41 if((a[j]<a[i])&&(b[j]+1>b[i]))
42
43 b[i]=b[j]+1;
44
45 }
46
47 for(i=1; i<=n; i++)
48
49 if(c[i]+b[i]>m)
50
51 m=c[i]+b[i];
52
53 printf("%d",n-m+1);
54
55 }