[NOIP2004]合唱队形【动态规划】

【问题描述】

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

    
合唱队形是指这样的一种队形:设K位同学从左到右依次编号为12…K,他们的身高分别为T1T2TK  则他们的身高满足T1<...Ti+1>…>TK(1<=i<=K)

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

【输入文件】

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

【输出文件】

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

解题思路:这题的方法还是比较明显的,就是经典的最长不降与不升子序列的结合,枚举1到n作为中间的人,中间为i时,DP求出1到i的最长不降子序列和i到n的最长不升子序列,注意求出来之后i一定要在序列中,然后不断更新答案即可。

 

代码(前几年的代码都年代久远了QAQ):

program chorus(input,output);
var f:array[1..150]of longint;
a,ff:array[1..150]of longint;
i,n,k:longint;
function dps(s,e:longint):longint;
var i,j:longint;
begin
for i:=s to e do
 for j:=s to i do
  if (a[j]<=ff[j]) thenff[i]:=ff[j]+1;
dps:=0;
for i:=s to e do if ff[i]>dps then dps:=ff[i];
for i:=1 to n do ff[i]:=1;
end;
function dpj(s,e:longint):longint;
var i,j:longint;
begin
for i:=s to e do
 for j:=s to i do
  if(a[j]>a[i])and(ff[i]<=ff[j]) then ff[i]:=ff[j]+1;
dpj:=0;
for i:=s to e do if ff[i]>dpj then dpj:=ff[i];
for i:=1 to n do ff[i]:=1;
end;
begin
readln(n);
for i:=1 to n do read(a[i]);
fillchar(f,sizeof(f),1);
for i:=1 to n do ff[i]:=1;
k:=maxlongint;
for i:=1 to n do
 begin
 f[i]:=n-(dps(1,i)+dpj(i+1,n));
 if f[i]
 end;
writeln(k);
end.


你可能感兴趣的:(NOIP)