【动态规划】合唱团(动态规划)(最长上升子数列)

【动态规划】合唱团

时间限制: 1 Sec  内存限制: 64 MB
提交: 5  解决: 4
[提交][状态][讨论版]

题目描述

N 位同学站成一排,墨老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形。合唱队形是指这样的一种队形:设K位同学从左到右依次编号为 1,2,…,K,他们的身高分别为T1,T2,…,TK,  则他们的身高满足T1<T2<…<Ti>Ti+1>…>TK(1≤i≤K)。

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

输入

第一行是一个整数N(2≤N≤100),表示同学的总数。第一行有n个整数,用空格分隔,第i个整数Ti(130≤Ti≤230)是第i位同学的身高(厘米)。

输出

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

样例输入

8
186 186 150 200 160 130 197 220

样例输出

4

提示

对于50%的数据,保证有n≤20;

对于全部的数据,保证有n≤100。

【分析】一个最长上升子数列和一个最长下降子数列。

 

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <time.h>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#define inf 0x3f3f3f3f
#define mod 1000000007
typedef long long ll;
using namespace std;
const int N=110;
int n,dp[N],i,j,len;
int main() {
    cin>>n;
    int  a[N];
    for(int i=0; i<n; i++) {
        cin>>a[i];
    }
    if(n==2) {
        cout<<"0"<<endl;
        exit(0);
    }
int flag;
    int maxn=0;
    for(int  i=1; i<n-1; i++) {
        int ans1=0,ans2=0;
        memset(dp,0,sizeof(dp));
        dp[0]=1;
        for(int j=1; j<=i; j++) {
                dp[j]=1;
            for(int k=0; k<j; k++) {
                if(a[j]>a[k])dp[j]=max(dp[j],dp[k]+1);
            }
            ans1=max(ans1,dp[j]);
        }
        dp[i]=1;flag=0;
        for(int j=i+1; j<n; j++) {
            dp[j]=1;
            for(int k=i; k<j; k++) {
                if(a[k]>a[j])dp[j]=max(dp[j],dp[k]+1);
            }
            ans2=max(ans2,dp[j]);
        }
        if(ans1+ans2>maxn){
        maxn=max(maxn,ans1+ans2);
        if(ans1==1||ans2==1)flag=1;
        }
    }
    if(!flag)cout<<n-maxn+1<<endl;
    else cout<<n-maxn<<endl;
    return 0;
}
View Code

 

 

 

posted @ 2016-07-29 12:26  贱人方  阅读(325)  评论(0编辑  收藏  举报