求几道pascal题目,最好带答案的

如题所述

第1个回答  2013-07-25
给你一道编程题 合唱队形(chorus.pas/c/cpp)来源:NOIP2004(提高组) 第一题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包括一行,这一行只包含一个整数,就是最少需要几位同学出列。【样例输入】8186 186 150 200 160 130 197 220【样例输出】4【数据规模】对于50%的数据,保证有n<=20;对于全部的数据,保证有n<=100。PS:所谓的合唱队队形就是中间最高然后依次从两边递减。题目要求出队人数最少,于是我们可以抽象的想象成从左到最高的人是最长上升子序列,从最高人的人到右边是最长下降子序列。我们来看一下复杂度:如果采用枚举中间人的话,计算最长上升或下降子序列复杂度O(n^2)一共求N次,所以复杂度变为O(n^3)。这个复杂度对这题的数据已经可以解决,但不是最优的方法。其实最长上升或下降子序列只要一次就可以了,因为最长最长上升或下降子序列不受中间人的影响。只要用OPT1求一次最长上升子序列,OPT2求一次最长下降子序列。这样答案就是N-max(opt1[i]+opt2[i]-1).(i是从1到n)。这样我们就把复杂度从O(n^3)降到了O(n^2)。参考程序:program chorus;constmaxn=200;varopt1,opt2,a:array[0..maxn] of longint;n,ans:longint;procedure init;vari:longint;beginassign(input, 'chorus.out');reset(input);assign(output, 'chorus.in');rewrite(output);readln(n);for i:=1 to n do read(a[i]);end;procedure main;vari,j:longint;begina[0]:=-maxlongint;for i:=1 to n do for j:=i-1 downto 0 do if (a[j]<a[i]) and (opt1[j]+1>opt1[i]) then opt1[i]:=opt1[j]+1;a[n+1]:=-maxlongint;for i:=n downto 1 do for j:=i+1 to n+1 do if (a[j]<a[i]) and (opt2[j]+1>opt2[i]) then opt2[i]:=opt2[j]+1;ans:=0;for i:=1 to n do if opt1[i]+opt2[i]>ans then ans:=opt1[i]+opt2[i];end;procedure print;beginwriteln(n-ans+1);close(input);close(output);end;begininit;main;print;end.
相似回答
大家正在搜