ZOJ1025-最長下降子序列


ZOJ1025-Wooden Sticks 加工木棒問題

【問題描述】

現有n根木棒,已知它們的長度和重量。要用一部木工機一根一根地加工這些木棒。該機器在加工過程中需要一定的准備時間用於清洗機器、調整工具和模板。

木工機需要的准備時間如下:

(1)   第一根木棒需要1min的准備時間;

(2)   在加工了一根長為l,重為w的木棒后,接着加工一根長為l’(l≤l’),

重為w’(w≤w’)的木棒是不需要任何准備時間的,否則需要1min的准備時間。

給定n根木棒,你要找到最少的准備時間。例如現在有長度和重量分別為(4,9)、(5,2)、(2,1)、(3,5)和(1,4)的5根木棒,那么所需准備時間最少為2min,順序為(1,4)-》(3,5)-》(4,9)-》(2,1)-》(5,2)。

【輸入】

輸入有多組測試例。輸入數據的第一行是測試例的個數T。

每個測試例兩行:

第一行是一個整數n(1≤n≤5000),表示有多少根木棒;

第二行包括n×2個整數,表示l1,w1,l2,w2,l3,w3,…,ln,wn,全部不大於10000,其中li和wi表示第i根木棒的長度和重量。

數據由一個或多個空格分隔。

【輸出】

輸出是以分鍾為單位的最少准備時間,一行對應一個測試例。

【輸入樣例】                                       

3                                                  

5                                                  

4 9 5 2 2 1 3 5 1 4                                

3

2 2 1 1 2 2

3

1 3 2 2 3 1

【輸出樣例】

2

1

3


 

思路:

拿分析的樣例來看,直接想到了離散上的偏序集,但只是想到了,不知道該怎么解。。。

看了下題解有了思路。先通過一輪cmp構造的排序,將問題進行轉化——按照每個棒子的長度從小到大進行排序,然后得到基於棒子長度從小到大排序的棒子重量數組,將這個數組提取到w中保存,或者你不提出來也行,我就是為了方便,我稱之為空間換簡潔。

然后我們在把2維的偏序關系降到1維后(對,這個題就是降維打擊:),就發現現在問題已經轉換成了求w數組的最長上升子序列的最小個數,而這個問題,可以再次轉換成求w數組的最長遞減子序列的長度。后者的轉換很容易理解,比如這個數組w的最長遞減子序列的長度為5,那這5個值肯定各自在一個獨立的最長上升子序列中

兩行大概就把問題的核心說清了,然后coding


 

#include <iostream>
#include <cstring>
#include <algorithm>
#define N 5007
using namespace std;

int n,T;
struct stick{
    int l,w;
} sticks[N];
int w[N];
int dp[N];

bool cmp(stick a,stick b)
{
    if(a.l == b.l)
        return a.w < b.w;
    else if(a.l < b.l)
        return true;
    return false;
}

int LIS(int* w)
{
    int j;//j為當前最大結束點的坐標 
    dp[j=1] = w[1];
    for(int i = 2;i <= n;i++)
    {
        if(w[i] < dp[j]) 
            dp[++j] = w[i];
        else if(w[i] == dp[j]) continue;
        else {
            for(int k = j;k >= 1;k--)
            {
                if(k == 1) 
                    dp[1] = w[i]>dp[1]?w[i]:dp[1];
                //找到所有“合適”的位置 
                if(w[i]>dp[k] && w[i]<dp[k-1]) 
                    dp[k] = w[i];
            }
        }
    }
    return j;
}

int main()
{
    cin>>T;
    while(T--)
    {
        cin>>n;
        int ans = 0;
        for(int i = 1;i <= n;i++)
            cin>>sticks[i].l>>sticks[i].w;
        sort(sticks+1,sticks+1+n,cmp);
        for(int i = 1;i <= n;i++) 
            w[i] = sticks[i].w;
        cout<<LIS(w)<<endl;
    }
    return 0;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM