//合唱队
/*解题思路:
实际上这是一道简单动态规划的题。但是一眼看上去不是很直观。题目所谓的合唱队形就是一个最长上升子序列的拼接。
只要求出从队列首到位置 i 的最长上升子序列长度加上从队尾开始到位置 i 的最长上升子序列的长度就能求出合唱队形的总长度。
我们还知道总的人数,减一下就能得出要出列的人数了。*/
/*求最长上升子序列:
现在有一个序列,要求他的最长上升子序列。直观上并不是很好求得,反过来看的话就能比较好理解:
现在对于总序列里的第i个元素来说,包含元素i的最长子序列是多少呢?如果i前面有能构成最长上升序列的(设它为j),而且i数值比j大,
那很显然到第i个元素(包含元素i)的最长子序列是到第j个元素的最长子序列 + 1;否则到第i个元素(包含元素i)的最长子序列就是是1。
因为前面没有比他更小的了,只有自身构成一个子序列。*/
#include<iostream>
#include<string>
using namespace std;
#define Max 200
int main()
{
int inc[Max], dec[Max], h[Max];//inc表示最大递增序列,dec表示从尾部开始反向递增最大序列即最大递减序列
int n, number=0;
cin >> n;//输入N位同学
for (int i = 0; i < n; i++)
cin >> h[i];//输入N位同学的身高
for (int i = 0; i<n; i++)//求最长上升子序列
{
inc[i] = 1;
for (int j = 0; j<i; j++)
if (h[i]>h[j] && inc[j] + 1>inc[i])
inc[i] = inc[j] + 1;
}
for (int k = n - 1; k >= 0; k--)//求最长下降子序列--或者说从后往前的上升序列
{
dec[k] = 1;
for (int j = n - 1; j > k; j--)
if (h[k] > h[j] && dec[j] + 1 > dec[k])
dec[k] = dec[j] + 1;
}
for (int i = 0; i<n; i++)
if (inc[i] + dec[i]>number)
number = inc[i] + dec[i];
number = n - number + 1;
cout << number << endl;
return 0;
}
华为OJ题目(十一):合唱队
最新推荐文章于 2019-08-06 10:46:59 发布