动规——合唱队形

这是以前写的==转过来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 }

 

转载于:https://www.cnblogs.com/Franky-ln/p/5563238.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值