Pascal编程题(合唱队形)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Pascal编程题(合唱队形)相关的知识,希望对你有一定的参考价值。

【试题描述】

茵茵所在的合唱队共有 N 个人( N 为奇数)。为了准备一次演出,老师开始为她们安排合唱队形了。
大家都知道,合唱队形通常是中间高两端低的。老师是这样安排他们的队形的:先让所有的同学按高个儿在前的顺序排成一队。然后,最高的那位同学单独站出来,这是合唱队形的中心,再让第二位同学站在她的左手边,让第三位同学站在她的右手边,再依次向两端安排其他人……
事先给定所有人的身高,请输出她们站成合唱队形之后的身高顺序。

【输入描述】

第一行是一个整数 ,表示合唱队的总人数,已知 N 为奇数,且 1 ≤ N ≤ 51 。
第二行是 N 个整数,表示以厘米为单位的所有人的身高。

【输出描述】

只有 N 个整数,表示她们按老师的要求站成合唱队形之后的身高顺序。

【输入样例】

7
154 160 157 162 159 152 163

【输出样例】

152 157 160 163 162 159 154

呵呵。我们先瞥开dp不看。解决这个问题我们这么考虑:
肯定有一个中间人,然后在他左边的人都要比他矮,并且是单调上升;在他右边的人肯定要比他矮,并且是单调下降!那么我们有了这个中间人,并且知道他的身高和他的位置,然后就是做左边的最长单调上升序列,加上右边的最长单调下降序列!
这个中间人,我们来枚举他,那么是不是只要解决最长单调上升序列和最长单调下降序列了?
这个单调上升序列和单调下降序列就用dp来求解!求解单调下降序列其实就是把一个数列反过来求最长单调上升序列吧?那么我就来讲一下单调上升序列。

给一个序列,求最长单调上升序列,我们用up[i]表示从第一个人到第i个人,最长的序列长。(就是到第i个人,必须身高单调上升,最多取多少人)
显然up[1]=1。
up[2]等于什么?如果2这个人比1高,那么up[2]=up[1]+1,要不就等于1是吧?
我们知道了up[1]和up[2]能不能知道up[3]呢?当然可以!因为如果3的人比2高,那么up〔3〕的值就可以取up[2]+1!
于是我们可以得出结论:
第i个人如果比第j个人高(i>j),那么up[i]就可以取up[j]+1!
那么就得出:
Up[i]=maxup[j]+1((0<j<i) and a[j]<a[i]),up[i-1]

这里你还要注意一个问题,就是求出这个,但是a[i]必须小于中间人高度,这个up[i]才可取~

理解了么?

我们枚举一个中间人,ans=左边最长单调上升序列+右边最长单调下降序列+1(1就是中间这个人)

一个中间人对应一个ans,枚举中间人,求出最大的ans
==========================
我觉得说得很清楚了丫,up[i]表示到第i个人的最长上升子序列。
如果a[i]>a[j](i>j),那么up[i]的值就可以取up[j]+1(就是到第i个人的最长上升子序列加上第i个人)
于是我们对所有i,对j做一个循环。
得出Up[i]=maxup[j]+1((0<j<i) and a[j]<a[i]),up[i-1]

参考资料:http://zhidao.baidu.com/question/110019362.html

参考技术A var f,d:array[1..100]of longint;
a,i,j,k,t:longint;
begin
readln(a);
for i:=1 to a do
read(f[i]);
for i:=1 to a-1 do
begin
k:=i;
for j:=i+1 to a do
if f[j]>f[k] then k:=j;
if i<>k then
begin
t:=f[i];
f[i]:=f[k];
f[k]:=t;
end;
end;j:=round((a+1)/2);k:=0;
for i:=1 to a do
begin
if i mod 2<>0 then d[j-k]:=f[i];
if i mod 2=0 then begin k:=k+1;d[j+k]:=f[i]; end;
end;
for i:=1 to a do
write(d[i],' ');writeln;
end.本回答被提问者采纳
参考技术B 顶一楼的。。这好像是那一年小学组的pascal题,,水题一道,根本用不上DP。。先对数据进行排序,然后先把排序后数据中的第一小的,第二小的,。。。一直到第N div 2 个小的数打出来,然后打最大数,然后再打第二大的,第四大的,。。。第n-1个大的。。你自己去实现程序吧 参考技术C program queue(input,output);
var
a,tx:array[1..51] of integer;
n:integer;
i,j,t:integer;
begin
read(n);
for i:=1 to n do read(a[i]); //(1)
for i:=1 to n-1 do
for j:=i+1 to n do
if a[j]>a[i] then begin t:=a[i];a[i]:=a[j];a[j]:=t;end; //(2)
tx[(n div 2)+1]:=a[1]; //(3)
for i:=2 to n do
if odd(i)=true
then tx[(n div 2)+1-(i div 2)]:=a[i]
else tx[(n div 2)+1+(i div 2)]:=a[i]; //(4)
for i:=1 to n do write(tx[i],' '); //(5)
end.

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的第一行是一个整数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。

题解:一遍正序的最长上升子序列+一遍到序的最长上升子序列,注意中间重叠,ans:n-tot

#include<cstdio>
#include<iostream>
using namespace std;
#define N 1010
int p[N],f[N],a[N],n,tot;
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]),f[i]=1,p[i]=1;
    for(int i=1;i<=n;i++)
        for(int j=i-1;j>=1;j--)
            if(a[i]>a[j]) f[i]=max(f[i],f[j]+1);
    for(int i=n;i>=1;i--)
        for(int j=i+1;j<=n;j++)
            if(a[i]>a[j]) p[i]=max(p[i],p[j]+1);
    for(int i=1;i<=n;i++)
        if(p[i]+f[i]-1>tot)
           tot=p[i]+f[i]-1;
    printf("%d\n",n-tot);
    return 0;
}

 

以上是关于Pascal编程题(合唱队形)的主要内容,如果未能解决你的问题,请参考以下文章

合唱队形

洛谷P1091合唱队形

网易2017春招笔试真题编程题集合——调整队形

UOJ #214 合唱队形 (概率期望计数DPMin-Max容斥)

bzoj千题计划211:bzoj1996: [Hnoi2010]chorus 合唱队

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