[P1091]合唱队列 - 动态规划

洛谷P1091

题目描述

N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形。

合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2…,K,他们的身高分别为T1,T2,…,TK, 则他们的身高满足T1<...

输入格式:

输入文件chorus.in的第一行是一个整数N(2<=N<=100),表示同学的总数。第一行有n个整数,用空格分隔,第i个整数Ti(130<=Ti<=230)是第i位同学的身高(厘米)。

输出格式:

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

输入输出样例

输入样例#1:复制

8
186 186 150 200 160 130 197 220

输出样例#1:复制

4

说明

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

对于全部的数据,保证有n<=100

不说啥,贴代码,看注释就好

#include <bits/stdc++.h>
using namespace std;

int n;
int a[101];
int f1[101];
int f2[101];
//f1[i]表示当i是中间身高最大值时,左边留下的人(左边最长上升序列长度)
//f2[i]...
int max(int a, int b)
{
    return a > b ? a : b;
}

int main()
{
    //freopen("testdata.in", "r", stdin);
    int ans = 0;
    //ans表示留下来的人数。
    //踢掉的人数最少,就是留下的人最多。
    cin >> n;
    for (int i=1; i<=n; i++)
        cin >> a[i];

    f1[1] = 0;
    f2[n] = 0;
    //设置起始(其实我也不知道要不要)
    //求[1 -> n]的最长上升序列
    //i表示假设a[i]是中间最高一个
    for (int i=1; i<=n; i++)
    {
        for (int k=0; k<i; k++)
            if (a[i] > a[k])            //如果a[i] <= a[k]就不用考虑
                f1[i] = max(f1[i], f1[k]+1);
                //注意这里f1下标写的i
    }
    for (int i=n; i>0; i--)     //求[n -> 1]的最长上升序列
    {
        for (int k=n+1; k>i; k--)
            if (a[i] > a[k])            //如果a[i] <= a[k]就不用考虑
                f2[i] = max(f2[i], f2[k]+1);
    }
    for (int i=1; i<=n; i++)
        ans = max(f1[i]+f2[i]-1, ans);
        //遍历i,计算留下的人数,-1是因为a[i]重复算了
    cout << n - ans << endl;
    //ans表示留下的人数,所以用n - ans表示踢出去的人数(好惨)
    return 0;
}

原文地址:https://www.cnblogs.com/TonyLiang2018/p/8412547.html

时间: 2024-10-05 11:27:48

[P1091]合唱队列 - 动态规划的相关文章

合唱队形(动态规划)

Description N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形. 合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1, 2, -, K,他们的身高分别为T1, T2, -, TK,则他们的身高满足T1 < T2 < - < Ti , Ti > Ti+1 > - > TK (1 <= i <= K). 你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形. Inp

codevs1058 合唱队形==洛谷P1091 合唱队形

P1091 合唱队形 题目描述 N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形. 合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2…,K,他们的身高分别为T1,T2,…,TK, 则他们的身高满足T1<...<Ti>Ti+1>…>TK(1<=i<=K). 你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形. 输入输出格式 输入格式: 输入文件chorus.in的第一行是

合唱队列

洛谷1091 合唱队列 觉得自己就是个ZZ,打眼一看,没思路,一看数据,n<=100,这不会是大法师吧...于是打暴力,快一小时(加上30分钟下课~~哦,下课时和陈国凯聊了一会QQ,%%%学神,mac啊)也没调出来,信心倍搓,然后放弃,看题解,哦cao,是最长上升子序列,然后秒掉了......... 先正着做一遍LIS,再倒着来一遍LIS,再枚举中间最高的人,正反求和,取最大,最后用n减去ans再减一,因为最高的人被算了两次. #include<bits/stdc++.h> using

P1091 合唱队形(LIS)

题目描述 NNN位同学站成一排,音乐老师要请其中的(N−KN-KN−K)位同学出列,使得剩下的KKK位同学排成合唱队形. 合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2,…,K1,2,…,K1,2,…,K,他们的身高分别为T1,T2,…,TKT_1,T_2,…,T_KT1?,T2?,…,TK?, 则他们的身高满足T1<...<Ti>Ti+1>…>TK(1≤i≤K)T_1<...<T_i>T_{i+1}>…>T_K(1 \le i

[NOIP2004] 提高组 洛谷P1091 合唱队形

题目描述 N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形. 合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2…,K,他们的身高分别为T1,T2,…,TK, 则他们的身高满足T1<...<Ti>Ti+1>…>TK(1<=i<=K). 你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形. 输入输出格式 输入格式: 输入文件chorus.in的第一行是一个整数N(2<

洛谷 P1091 合唱队形 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:https://www.luogu.org/problem/show?pid=1091 题目描述 N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形. 合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2…,K,他们的身高分别为T1,T2,…,TK, 则他们的身高满足T1<...<Ti>Ti+1>…>TK(1<=i<=K). 你的任务是,

P1091 合唱队形

题目描述 N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形. 合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2-,K,他们的身高分别为T1,T2,-,TK, 则他们的身高满足T1<...<Ti>Ti+1>->TK(1<=i<=K). 你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形. 输入输出格式 输入格式: 输入文件chorus.in的第一行是一个整数N(2<

Luogu P1091 合唱队形

思路 看题目中给出的式子,其实就是一半是最长上升子序列,一半是最长下降子序列.那么就需要进行两次DP,第一次求最长上升子序列,第二次求最长下降子序列,然后枚举序列的最高点.这个从这个最高点劈开.维护一个最大的值.到最后有总人数减去最大值 代码 #include <iostream> #include <cstring> #include <cstdio> using namespace std; int dp[233], n, t[123], ans, f[233],

P1091 合唱队形 最长上升子序列

思路:最长上升子序列 正着做一遍 倒着做一遍 然后 取最大值 #include<bits/stdc++.h> using namespace std; const int maxn=105; int dp[maxn],dp1[maxn],a[maxn]; int main(){ int n; cin>>n; for(int i=1;i<=n;i++)scanf("%d",&a[i]); for(int i=1;i<=n;i++){ dp[i]