0
点赞
收藏
分享

微信扫一扫

合唱队形---【dp】

Xin_So 2022-01-31 阅读 67

问题描述:

N 位同学站成一排,音乐老师要请其中的 (N−K) 位同学出列,使得剩下的 K 位同学排成合唱队形。     

合唱队形是指这样的一种队形:设 K 位同学从左到右依次编号为1,2…,K,他们的身高分别为 T1,T2,…,TK,  则他们的身高满足 T1<…<Ti>Ti+1>…>TK(1≤i≤K)。     

你的任务是,已知所有 N 位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。

输入格式

输入的第一行是一个整数 N,表示同学的总数。

第二行有 N 个整数,用空格分隔,第 i 个整数 Ti 是第 i 位同学的身高(厘米)。

输出格式

输出包括一行,这一行只包含一个整数,就是最少需要几位同学出列。

数据范围

2≤N≤100
130≤Ti≤230

输入样例:

8
186 186 150 200 160 130 197 220

输出样例:

4

        解题思路:

枪打出头鸟:可以以最高的那位同学 s 为分界线分为两部分,左边求以 s 结尾的最大上升子序列--->f[i]=max(f[i],f[j]+1)(j=0,1,2,...i-1),右边求以 s 开头的最大下降子序列,又因为 s 求了两次,所以应左右两边相加然后再减1;最后在枚举这位最高的同学 s ,求得最大值即为最终结果。其代码如下:

#include<bits/stdc++.h>
using namespace std;
int n,a[110];
int f[110],g[110];
//枪打出头鸟
//状态计算--以最高的同学为分割线来分成两部分
int main()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];

for(int i=1;i<=n;i++)//最长上升子序列模板(递归)
{
f[i]=1;//只有a[i]一个数
for(int j=1;j<i;j++)
{
if(a[j]<a[i])
{
f[i]=max(f[i],f[j]+1);
}
}
}
for(int i=n;i>0;i--)//最长下降子序列
{
g[i]=1;
for(int j=n;j>i;j--)
{
if(a[j]<a[i])
{
g[i]=max(g[i],g[j]+1);
}
}
}
int ans=0;
for(int i=1;i<=n;i++) ans=max(ans,f[i]+g[i]-1);//分割点加了两次
cout<<n-ans<<endl;
return 0;
}

举报

相关推荐

0 条评论