洛谷 P1091 合唱隊形 解題報告
題目描述
NN 位同學站成一排,音樂老師要請其中的( N-KN?K )位同學出列,使得剩下的 KK 位同學排成合唱隊形。
合唱隊形是指這樣的一種隊形:設K位同學從左到右依次編號為 1,2,…,K1,2,…,K ,他們的身高分別為 T_1,T_2,…,T_KT1?,T2?,…,TK? , 則他們的身高滿足 T_1<...<T_i>T_{i+1}>…>T_K(1 \le i \le K)T1?<...<Ti?>Ti+1?>…>TK?(1≤i≤K) 。
你的任務是,已知所有N位同學的身高,計算最少需要幾位同學出列,可以使得剩下的同學排成合唱隊形。
輸入輸出格式
輸入格式:
共二行。
第一行是一個整數 N(2 \le N \le 100)N(2≤N≤100) ,表示同學的總數。
第二行有 nn 個整數,用空格分隔,第 ii 個整數 T_i(130 \le T_i \le 230)Ti?(130≤Ti?≤230) 是第 ii 位同學的身高(厘米)。
輸出格式:
一個整數,最少需要幾位同學出列。
輸入輸出樣例
輸入樣例#1: 復制8 186 186 150 200 160 130 197 220輸出樣例#1: 復制
4
讀題可以發現,本題要求的是一個兩邊低中間高的序列,那麽為了保證出隊的人數盡量少,留下來的人數就要多,可以考慮把序列分成兩段,一段1---i,一段i+1---k,則題目轉化為在一段遞增(遞減)的區間中留下最多人;由此可以想到最長不下降子序列,由於有一邊是遞減的,所以從兩邊各跑一遍,然後跑一遍所有人,取max(f[左]+f[右]-1)即可(-1的原因是中間被多算了一次)
AC代碼:
#include<bits/stdc++.h>
using namespace std;
const int MAXN=105;
int f[2][MAXN],a[MAXN],n,maxx;
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i],f[0][i]=f[1][i]=1;
for(int i=1;i<=n;i++)
for(int j=1;j<i;j++)
if(a[i]>a[j])
f[0][i]=max(f[0][i],f[0][j]+1);
for(int i=n;i>=1;i--)
for(int j=n;j>i;j--)
if(a[i]>a[j])
f[1][i]=max(f[1][i],f[1][j]+1);
for(int i=1;i<=n;i++)
maxx=max(maxx,f[1][i]+f[0][i]-1);
cout<<n-maxx;
return 0;
}
參考大佬@XSamsara題解
洛谷 P1091 合唱隊形 解題報告