题目:H - 合唱队形
N位同窗站成一排,音乐老师要请其中的(N-K)位同窗出列,使得剩下的K位同窗不交换位置就能排成合唱队形。
合唱队形是指这样的一种队形:设K位同窗从左到右依次编号为1, 2, …, K,他们的身高分别为T1, T2, …, TK,则他们的身高知足T1 < T2 < … < Ti , Ti > Ti+1 > … > TK (1 <= i <= K)。
你的任务是,已知全部N位同窗的身高,计算最少须要几位同窗出列,能够使得剩下的同窗排成合唱队形。
Input
输入的第一行是一个整数N(2 <= N <= 100),表示同窗的总数。第一行有n个整数,用空格分隔,第i个整数Ti(130 <= Ti <= 230)是第i位同窗的身高(厘米)。
Output
输出包括一行,这一行只包含一个整数,就是最少须要几位同窗出列。
Sample Input
8
186 186 150 200 160 130 197 220
Sample Output
4数组
思路:用两个dp数组,一个用来存正向递增,一个用来存反向递增,而后最后对应相加,再求一个最大的子序列,(这里要求的是宽度,不是数值的和,因此都再清0以后,有相应的则进行+1,具体看代码就知道了);code
注意:避免在两次寻找最优子序列的时候将其自己给重复进行相加了!!!string
新技巧:经过找正向与反向的双向递增子序列,这样就能够解决有峰值的最优子序列问题;io
代码:技巧
#include<stdio.h> #include<string.h> int a[105],dp_left[105]; int dp_right[105],dp[105]; int main() { int n,i,j,s; while(scanf("%d",&n)!=EOF){ memset(dp_left,0,sizeof(dp_left )); memset(dp_right,0,sizeof(dp_right )); for(i=0;i<n;++i) scanf("%d",&a[i]); for(i=1;i<n;++i){ for(j=0;j<i;j++){ if(a[i]>a[j]) dp_left[i]=dp_left[i]>(dp_left[j]+1)?dp_left[i]:(dp_left[j]+1); //就是这个位置,只须要进行加的操做便可; } } for(i=n-1;i>=0;--i){ for(j=n-1;j>i;j--){ if(a[i]>a[j]) dp_right[i]=dp_right[i]>(dp_right[j]+1)?dp_right[i]:(dp_right[j]+1); } } for(i=0;i<n;++i) dp[i]=dp_left[i]+dp_right[i]+1;//个人操做是一开始就没有算其自己 int k=0; //全部在这个求和的时候要加上其自己 for(i=1;i<n;++i) if(dp[k]<dp[i]) k=i; s=n-dp[k]; printf("%d\n",s); } return 0; }