開啟章節選單

1062 Containers

題目連結

題目翻譯

貨櫃碼頭要把貨櫃疊成若干個堆,之後按照字母順序(A→B→C...)裝船。要求裝船時只能取每堆最頂端的貨櫃,請問最少需要幾堆才能做到?

每個貨櫃有一個大寫字母標示它要送上哪艘船。貨櫃按照輸入順序抵達,必須即時堆放。

輸入

多組測資,每行一個由大寫字母組成的字串,讀到 end 停止。

輸出

每組輸出 Case X: Y,Y 是最少堆數。

解題思路

核心規則:若貨櫃 C 放在 B 上面,則 C 的船必須比 B 更早裝(C ≤ B,字母序小的先裝)。換句話說,在一個堆裡,從底到頂字母必須非遞增(頂端最小)。

對每個新來的貨櫃 c,用 lower_bound 找第一個堆頂 ≥ c 的堆(找到第一個可以「壓在上面」的位置),把 c 放進去。若找不到就開新堆。

比較函數 return c > a.back()lower_bound 找到第一個「不滿足 c > 堆頂」的堆,也就是 c ≤ 堆頂的第一個,確保堆的非遞增性質得以維持。

這個做法類似耐心排序(Patience Sorting),最終堆數即為所求。

程式碼

//author: Piau
#include <bits/stdc++.h>
using namespace std;

#define pb push_back
#define fi first
#define se second
#define INF LONG_LONG_MAX/1000
#define WA() cin.tie(0)->sync_with_stdio(0)
#define all(x) (x).begin(), (x).end()
#define int long long
#define PII pair<int, int>

signed main() { WA();
    int t = 0;
    for (string s; cin >> s, s != "end";) { cout << "Case " << ++t << ": ";
        vector<vector<char>> v;
        for (auto &c : s) {
            auto it = lower_bound(all(v), c, [](vector<char> a, char c){
                return c > a.back();
            });
            if (it == v.end()) v.pb(vector<char>(1, {c}));
            else it->pb(c);
        }
        cout << v.size() << '\n';
    }
}