题目1131:合唱队形
题目的描述也比较清楚,需要找从前往后递增,并从该结束点开始从前往后递减。
使用两个最长不下降序列,一个表示从前往后不下降,另一个表示从后往前不下降。
例如对于图:
我们希望这样一个序列的长度是最长的。
很显然利用最长不下降序列DP可以得到从前往后的最长递增序列。
dp[i]表示前i个数据最长不下降序列的长度,对于第i个数据,它应当比前面某一个元素高才能形成以a[i]结尾的最长不下降序列。
于是我们遍历0~i-1的元素,找到a[j]<a[i] && dp[j]+1>dp[i]的数据,更新dp[i].
因为前面最长的序列+a[i]的长度已经是这一段最长,所以之后出现的元素不影响这一个位置最长不下降序列长度的大小;
总体空间复杂度O(N) 时间复杂度O(N^2)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<string>
#include<vector>
#include<ctype.h>
#define N 101
using namespace std;
int main(){
int n;
int a[N];
int dp1[N],dp2[N];
while(scanf("%d",&n)!=EOF){
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
dp1[i]=dp2[i]=1;
}
for(int i=0;i<n;i++){
for(int j=0;j<i;j++){
if(a[j]<a[i] && dp1[j]+1>dp1[i])
dp1[i]=dp1[j]+1;
}
}
for(int i=n-1;i>=0;i--){
for(int j=i+1;j<n;j++){
if(a[i]>a[j] && dp2[j]+1>dp2[i])
dp2[i]=dp2[j]+1;
}
}
int maxV=1;
for(int i=0;i<n;i++)
maxV=max(maxV,dp1[i]+dp2[i]-1);
printf("%d\n",n-maxV);
}
// system("pause");
return 0;
}