前言:
前几天某个同学问我这道dp,他说查了网上说用vector,我认为用数组就可以了,下面给大家讲一下
描述
N 位同学站成一排,音乐老师要请其中的( N−K )位同学出列,使得剩下的 K 位同学排成合唱队形。
合唱队形是指这样的一种队形:设K位同学从左到右依次编号为 1,2,…,K ,他们的身高分别为T1,T2,…,TK , 则他们的身高满足T1<…Ti+1>…>TK(1≤i≤K) 。
你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。
输入
共二行。
第一行是一个整数N(2≤N≤100) ,表示同学的总数。
第二行有 n 个整数,用空格分隔,第 i 个整数 Ti(130≤Ti≤230) 是第 ii 位同学的身高(厘米)。
输出
一个整数,最少需要几位同学出列。
样例
输入复制
8
186 186 150 200 160 130 197 220
输出复制
4
提示
对于50%的数据,保证有 n≤20 ;
对于全部的数据,保证有 n≤100 。
分析:
首先,先看提示,n≤100,那么就不用打太多优化,随后我们来分析题目
题目让我们在一段序列中找递增而不一定连续的最长子序列,这是关键。
那么我们就设3个数组:
a为身高序列,用来储存;
b为由左到右身高递增的人数序列,b[ i ]为a[ 1 ] 到 a[ i ] 中满足身高递增的最多人数;
c与b的统计顺序相反——从右到左;
这样明眼人一眼就能看出,该问题满足最优子结构性质。
显然,合唱队总人数即为 max{ b[ i ] + c[ i ] } -1(公式中 i 同学被重复算了,故减一)那么答案就是n减去合唱队人数了;
好,上代码:
#include<bits/stdc++.h>
using namespace std;
// 合唱队形;
int a[99999],b[99999],c[99999],n,i,j,maxx;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
for(int i=1;i<=n;i++){
b[i]=1;
for(int j=1;j<=i-1;j++){
if((a[i]>a[j]) && (b[j]+1>b[i])){
b[i]=b[j]+1;
}
}
}
//
for(int i=n;i>=1;i--){
c[i]=1;
for(int j=i+1;j<=n;j++){
if((a[i]>a[j]) && (c[j]+1>c[i])){
c[i]=c[j]+1;
}
}
}
//
maxx=0;
for(int i=1;i<=n;i++){
if(maxx<b[i]+c[i]){
maxx=b[i]+c[i];
}
}
//
maxx=n-maxx+1;
printf("%d",maxx);
}//时间复杂度O(n*n),100,能卡过
大家现在看懂了吗???