【题解】「NOIP2004」合唱队形(DP,最长不下降子序列)

2024-02-08 03:18

本文主要是介绍【题解】「NOIP2004」合唱队形(DP,最长不下降子序列),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题面

【题目描述】
N N N位同学站成一排,音乐老师要请其中的 ( N − K ) (N-K) (NK)位同学出列,使得剩下的K位同学排成合唱队形。
合唱队形是指这样的一种队形:设K位同学从左到右依次编号为 1 , 2 … , K 1,2…,K 12K,他们的身高分别为 T 1 , T 2 , … , T K T_1,T_2,…,T_K T1T2TK, 则他们的身高满足 T 1 < . . . < T i > T i + 1 > … > T K ( 1 < = i < = K ) T_1< ...< T_i> T_{i+1}> …> T_K(1< =i< =K) T1<...<Ti>Ti+1>>TK(1<=i<=K)
你的任务是,已知所有 N N N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。
【输入】
第一行是一个整数 N ( 2 < = N < = 100 ) N(2< =N< =100) N(2<=N<=100),表示同学的总数。第一行有 n n n个整数,用空格分隔,第 i i i个整数 T i ( 130 < = T i < = 230 ) T_i(130< =T_i< =230) Ti(130<=Ti<=230)是第 i i i位同学的身高(厘米)。
【输出】
一行只包含一个整数,就是最少需要几位同学出列。
【样例输入】

8
186 186 150 200 160 130 197 220

【样例输出】

4

【数据范围】
对于 50 % 50\ % 50 的数据,保证有 n < = 20 n< =20 n<=20; 对于全部的数据,保证有 n < = 100 n< =100 n<=100

算法分析

根据题意,最后找出的同学身高的队形就是一个三角形。中间有一个同学身高最高,往左、往后身高依次递减。
假设最高是第 x x x位同学,则左边到x需要找一个最长不下降子序列,右边需要找一个最长不上升子序列。
定义数组 d p 1 [ i ] dp1[i] dp1[i],表示以 i i i为结尾的最长不下降子序列;
定义数组 d p 2 [ i ] dp2[i] dp2[i],表示以 i i i为开头的最长不上升子序列。
因此,可以枚举中间同学的编号 x x x,找出左边的最长不下降子序列,右边的最长不上升子序列,满足要求的人数就是: d p 1 [ x ] + d p 2 [ x ] − 1 dp1[x]+dp2[x]-1 dp1[x]+dp2[x]1(自身多加了一次, − 1 -1 1).
最后的答案就是 n − m a x n - max nmax{ d p 1 [ x ] + d p 2 [ x ] − 1 dp1[x]+dp2[x]-1 dp1[x]+dp2[x]1 } ( 1 < = x < = n ) (1<=x<=n) (1<=x<=n)
时间复杂度: O ( n 3 ) O(n^3) O(n3)

参考程序

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int a[110],dp1[110],dp2[100];
int main()
{int n,mid,ans=0,mx;cin>>n;for(int i=1;i<=n;i++)cin>>a[i];for(int i=1;i<=n;i++)	//中间最高的人是i{			for(int j=1;j<=i;j++)	//左边最长不下降子序列{mx=0;for(int k=1;k<j;k++){if(a[k]<a[j]){if(dp1[k]>mx)mx=dp1[k];}}dp1[j]=mx+1;}for(int j=n;j>=i;j--)	//右边最长不上升子序列{mx=0;for(int k=n;k>j;k--){if(a[k]<a[j]){if(dp2[k]>mx)mx=dp2[k];}}dp2[j]=mx+1;}//那么中间人最高的为i时,满足要求的人数是左边s人,右边dp[i]人,自身算了两次,-1ans=max(ans,dp1[i]+dp2[i]-1);}cout<<n-ans<<endl;return 0;
}

这篇关于【题解】「NOIP2004」合唱队形(DP,最长不下降子序列)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/689755

相关文章

hdu4826(三维DP)

这是一个百度之星的资格赛第四题 题目链接:http://acm.hdu.edu.cn/contests/contest_showproblem.php?pid=1004&cid=500 题意:从左上角的点到右上角的点,每个点只能走一遍,走的方向有三个:向上,向下,向右,求最大值。 咋一看像搜索题,先暴搜,TLE,然后剪枝,还是TLE.然后我就改方法,用DP来做,这题和普通dp相比,多个个向上

hdu1011(背包树形DP)

没有完全理解这题, m个人,攻打一个map,map的入口是1,在攻打某个结点之前要先攻打其他一个结点 dp[i][j]表示m个人攻打以第i个结点为根节点的子树得到的最优解 状态转移dp[i][ j ] = max(dp[i][j], dp[i][k]+dp[t][j-k]),其中t是i结点的子节点 代码如下: #include<iostream>#include<algorithm

hdu4865(概率DP)

题意:已知前一天和今天的天气概率,某天的天气概率和叶子的潮湿程度的概率,n天叶子的湿度,求n天最有可能的天气情况。 思路:概率DP,dp[i][j]表示第i天天气为j的概率,状态转移如下:dp[i][j] = max(dp[i][j, dp[i-1][k]*table2[k][j]*table1[j][col] )  代码如下: #include <stdio.h>#include

poj3261(可重复k次的最长子串)

题意:可重复k次的最长子串 解题思路:求所有区间[x,x+k-1]中的最小值的最大值。求sa时间复杂度Nlog(N),求最值时间复杂度N*N,但实际复杂度很低。题目数据也比较水,不然估计过不了。 代码入下: #include<iostream>#include<algorithm>#include<stdio.h>#include<math.h>#include<cstring

usaco 1.1 Broken Necklace(DP)

直接上代码 接触的第一道dp ps.大概的思路就是 先从左往右用一个数组在每个点记下蓝或黑的个数 再从右到左算一遍 最后取出最大的即可 核心语句在于: 如果 str[i] = 'r'  ,   rl[i]=rl[i-1]+1, bl[i]=0 如果 str[i] = 'b' ,  bl[i]=bl[i-1]+1, rl[i]=0 如果 str[i] = 'w',  bl[i]=b

poj 3974 and hdu 3068 最长回文串的O(n)解法(Manacher算法)

求一段字符串中的最长回文串。 因为数据量比较大,用原来的O(n^2)会爆。 小白上的O(n^2)解法代码:TLE啦~ #include<stdio.h>#include<string.h>const int Maxn = 1000000;char s[Maxn];int main(){char e[] = {"END"};while(scanf("%s", s) != EO

uva 10154 DP 叠乌龟

题意: 给你几只乌龟,每只乌龟有自身的重量和力量。 每只乌龟的力量可以承受自身体重和在其上的几只乌龟的体重和内。 问最多能叠放几只乌龟。 解析: 先将乌龟按力量从小到大排列。 然后dp的时候从前往后叠,状态转移方程: dp[i][j] = dp[i - 1][j];if (dp[i - 1][j - 1] != inf && dp[i - 1][j - 1] <= t[i]

uva 10131 最长子序列

题意: 给大象的体重和智商,求体重按从大到小,智商从高到低的最长子序列,并输出路径。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vect

uva 10118 dP

题意: 给4列篮子,每次从某一列开始无放回拿蜡烛放入篮子里,并且篮子最多只能放5支蜡烛,数字代表蜡烛的颜色。 当拿出当前颜色的蜡烛在篮子里存在时,猪脚可以把蜡烛带回家。 问最多拿多少只蜡烛。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cs

uva 10069 DP + 大数加法

代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <queue>#include <map>#include <cl