1. 程式人生 > >P1091 合唱隊形題解(洛谷,動態規劃LIS,單調佇列)

P1091 合唱隊形題解(洛谷,動態規劃LIS,單調佇列)

先上題目

P1091 合唱隊形(點選開啟題目)

題目解讀:

1.由T1<...<Ti​和Ti>Ti+1>>TK可以看出這題涉及最長上升子序列和最長下降子序列

2.注意點:當n=1時是允許的,就是說沒有因為i=1,Ti=T1,所以最後全部人都要出列這種說法

 

初步思路:

建立兩個函式,一個引數為l,r,判斷l~r內最長上升子序列的最大長度,另外一個函式判斷l~r內最長下降子序列的最大長度,無論你是先高後低,還是一路升高還是一路降低都可以用這兩個函式解決

讓i=1~n,然後最大的那個left(1,i)+right(i,n)-1就是能擁有的最大合唱團人數(減一是因為i在左右兩邊序列都有,重複了,所以減一

)

合唱團人數最多,當然被淘汰的人最少啦

 總人數-最多合唱團人數=最少剔除人數

上ac程式碼:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=100+10;
int f[maxn];
int a[maxn];
int n;

int left(int l,int r)//最長上升子序列
{
    for(int i=1;i<=n;i++)
        f[i]=1;//初始化為1
    for(int i=l;i<=r;i++)
        
for(int j=l;j<=i-1;j++) if(a[i]>a[j])//如果可以附加 f[i]=max(f[i],f[j]+1); int ans=f[1]; for(int i=l;i<=r;i++) ans=max(ans,f[i]); return ans;//這一段區間的最長上升子序列 } int right(int l,int r)//最長下降子序列 {///和上面差不多,加號改成減號而已 for(int i=1;i<=n;i++) f[i]
=1; for(int i=l;i<=r;i++) for(int j=l;j<=i-1;j++) if(a[i]<a[j])//如果可以附加///如果當前a[i]比較小 f[i]=max(f[i],f[j]+1); int ans=f[1]; for(int i=l;i<=r;i++) ans=max(ans,f[i]); return ans;//輸出最長下降子序列長度 } int main() { cin>>n;//輸入n for(int i=1;i<=n;i++) scanf("%d",&a[i]);//輸入資料 int temp_ans=1;//賦初值 for(int i=1;i<=n;i++)//讓ti=1~n,列舉各種ti {//temp_ans的意義是當ti為i時,符合條件的合唱團最大人數 temp_ans=max(temp_ans,left(1,i)+right(i,n)-1); } cout<<n-temp_ans<<endl;//總人數-最多合唱團人數=最少剔除人數 } /* 8 4 4 2 6 3 1222 5 7 */ /* 5 1 8 3 5 2 */