題目: UVa - 1062 - Containers

題目說明

給一個字串,代表依序進到港口的貨物,後面的貨物進來後就無法再移動前面的貨物,在港口的貨物須從下而上按照字典序的大而小排序,求最少堆成幾堆可以滿足條件。

解題思路

解法一:

將港口的每堆貨物視為一個 Stack,每次貨物進來後先檢查能否放在原本的 Stack 上,若無法則新增一個 Stack 後放入。最後輸出 Stack 的個數即可。

解法二:

延續解法一的想法,可以發現由左到右的 Stack 的 top() 其實就是 LIS,所以 Stack 的數量即為 LIS ( 最長嚴格遞增子陣列 ) 的長度,使用 DP 找出長度即可。

參考解法

解法一:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream>
#include <vector>
#include <string>
#include <stack>
#include <functional>

using namespace std;

static auto __ = []
{
ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
return 0;
}();

int main()
{
int cnt = 0;
string str;
vector<stack<char>> v;

auto AddToStack = [&](char& ch)
{
for (auto& s : v) if (ch <= s.top()) { s.push(ch); return; }
v.push_back(stack<char>());
v.back().push(ch);
};

while (cin >> str && str != "end")
{
v.clear();
for (auto& ch : str) AddToStack(ch);
cout << "Case " << ++cnt << ": " << v.size() << '\n';
}
}

解法二:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

static auto __ = []
{
ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
return 0;
}();

int main()
{
int cnt = 0;
string in;
while (cin >> in && in != "end")
{
int ret = 0, l = in.length();
vector<int> dp(l, 1);
for (int i = 0; i < l; ++i)
{
for (int j = i + 1; j < l; ++j)
if (in[j] > in[i]) dp[j] = max(dp[j], dp[i] + 1);
ret = max(ret, dp[i]);
}
cout << "Case " << ++cnt << ": " << ret << '\n';
}
}