DP - 最長上升子序列模型 - NOIP2004提高組 - 合唱隊形 + 北京大學ACM/ICPC選拔賽 - 登山

DP - 最長上升子序列模型 - NOIP2004提高組 - 合唱隊形 + 北京大學ACM/ICPC選拔賽 - 登山

1、合唱隊形 - NOIP 2004 提高組

N位同學站成一排,音樂老師要請其中的(N-K)位同學出列,使得剩下的K位同學排成合唱隊形。

合唱隊形是指這樣的一種隊形:設K位同學從左到右依次編號爲1,2…,K,他們的身高分別爲T1,T2,…,TK,  則他們的身高滿足T1<…Ti+1>…>TK(1≤i≤K)。

你的任務是,已知所有N位同學的身高,計算最少需要幾位同學出列,可以使得剩下的同學排成合唱隊形。

輸入格式
輸入的第一行是一個整數N,表示同學的總數。

第二行有n個整數,用空格分隔,第i個整數Ti是第i位同學的身高(釐米)。

輸出格式
輸出包括一行,這一行只包含一個整數,就是最少需要幾位同學出列。

數據範圍
2≤N≤100,
130≤Ti≤230

輸入樣例:
8
186 186 150 200 160 130 197 220
輸出樣例:
4

題意:

n使調調給定長度爲n的序列,要求從中去除一些數,\\使得剩下的數構成的序列是一個先嚴格單調遞增再嚴格單調遞減的序列。

ai>ai1>ai2>...>a1ai<ai+1<ai+2<...<an抽象地,有序列:a_i>a_{i-1}>a_{i-2}>...>a_1且a_i<a_{i+1}<a_{i+2}<...<a_n。

題解:

iresnres正反兩遍最長上升子序列求出以i爲中心的最長“凸”序列的長度res,再用n-res即得到去除的數的個數。


代碼:

#include<iostream>
#include<algorithm>

using namespace std;

const int N=110;

int n,f1[N],f2[N],a[N];

int main()
{
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    
    for(int i=1;i<=n;i++)
    {
        f1[i]=1;
        for(int j=1;j<i;j++)
            if(a[i]>a[j])
                f1[i]=max(f1[i],f1[j]+1);
    }
    
    for(int i=n;i;i--)
    {
        f2[i]=1;
        for(int j=n;j>i;j--)
            if(a[i]>a[j])
                f2[i]=max(f2[i],f2[j]+1);
    }
    
    int res=1;
    for(int i=1;i<=n;i++) res=max(res,f1[i]+f2[i]-1);
    
    cout<<n-res<<endl;
    
    return 0;
}

2、登山 - 第六屆北京大學程序設計大賽暨ACM/ICPC選拔賽

五一到了,ACM隊組織大家去登山觀光,隊員們發現山上一個有N個景點,並且決定按照順序來瀏覽這些景點,即每次所瀏覽景點的編號都要大於前一個瀏覽景點的編號。

同時隊員們還有另一個登山習慣,就是不連續瀏覽海拔相同的兩個景點,並且一旦開始下山,就不再向上走了。

隊員們希望在滿足上面條件的同時,儘可能多的瀏覽景點,你能幫他們找出最多可能瀏覽的景點數麼?

輸入格式
第一行包含整數N,表示景點數量。

第二行包含N個整數,表示每個景點的海拔。

輸出格式
輸出一個整數,表示最多能瀏覽的景點數。

數據範圍
2≤N≤1000

輸入樣例:
8
186 186 150 200 160 130 197 220
輸出樣例:
4

題解:

1同1,直接正反做兩遍最長上升子序列即可。

#include<iostream>
#include<algorithm>

using namespace std;

const int N=1010;

int n,a[N],f1[N],f2[N];

int main()
{
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    
    for(int i=1;i<=n;i++)
    {
        f1[i]=1;
        for(int j=1;j<i;j++)
            if(a[i]>a[j]) 
                f1[i]=max(f1[i],f1[j]+1);
    }
    
    for(int i=n;i;i--)
    {
        f2[i]=1;
        for(int j=n;j>i;j--)
            if(a[i]>a[j]) 
                f2[i]=max(f2[i],f2[j]+1);
    }
    
    int res=1;
    for(int i=1;i<=n;i++) res=max(res,f1[i]+f2[i]-1);
    
    cout<<res<<endl;
    
    return 0;
    
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章