# APCS實作題2021年1月第4題:飛黃騰達 > 日期:2024年8月10日 > 作者:王一哲 > [ZeroJudge 題目連結](https://zerojudge.tw/ShowProblem?problemid=f608) ## 題目 ### 問題描述 飛黃是一種生物,活在二維座標平面上。 有隻特別的飛黃一開始在座標 $(0, 0)$ 的位置,而且你知道它只會往右上方移動,也就是移動的時只可以走到 $x$ 座標跟 $y$ 座標都不比原本小的位置。 現在座標平面的第一象限上有 $n$ 個位置有果實,給定這 $n$ 個果實的座標,你想要知道這隻特別的飛黃最多可以吃到幾個果實。它必須移動到果實所在的座標才可以吃到果實。 <br /> ### 輸入說明 第一行有一個整數 $n$ 表示果實的數量。 接下來有 $n$ 行,第 $i$ 行的兩個整數 $x, y$ 表示第 $i$ 個果實位於 $(x, y)$ 座標。 保證不會有兩個果實在相同的位置。 配分 - 20分:$1 \leq n \leq 100, ~1 \leq x, y \leq 100$ - 30分:$1 \leq n \leq 1000, ~1 \leq x, y \leq 10^7$ - 50分:$1 \leq n \leq 200000, ~1 \leq x, y \leq 10^7$ <br /> ### 輸出格式 輸出一個數字表示最多可以吃到多少果實。 <br /> ### 範例輸入 ``` 3 1 1 2 5 3 2 ``` ### 範例輸出 ``` 2 ``` <br /><br /> ## Python 程式碼 假設目現所在的位置為 $(x, y)$,下一個果實的位置為 $(x_n, y_n)$,當 $x_n \geq x$ 且 $y_n \geq y$ 時,吃到的果實數量最大值才會增加。因此在第7或8行先將 fruit 依照果實 $x$ 座標由小到大排序,再從 fruit 依序讀取果實的 $y$ 座標,將 $y$ 由小到大插入另一個串列 st,最後 st 的長度就是答案。 費時最久約為 1.2 s,使用記憶體最多約為 32.6 MB,通過測試。 ```python= from bisect import bisect_right # 二分搜尋法 n = int(input()) # 讀取數量 n #fruit = [] # 儲存果實位置的串列 #for _ in range(n): # 讀取 n 行資料,轉成二個一組的整數數組再加到 fruit # fruit.append(tuple(map(int, input().split()))) #fruit.sort() # 依照果實 x 座標由小到大排序 fruit = sorted([tuple(map(int, input().split())) for _ in range(n)]) # 效果與第4 ~ 7行相同 st = [] # 果實 y 座標要遞增 for _, y in fruit: # 依序由 fruit 讀取資料 if not st or y >= st[-1]: st.append(y) # 如果 st 是空的或 y 大於等於 st[-1],找到新的果實,加到 st else: st[bisect_right(st, y)] = y # 否則用 bisect_right 找到於 st 中插入 y 的右側位置,重設值為 y print(len(st)) # st 的長度就是答案 ``` <br /><br /> ## C++ 程式碼 費時最久約為 0.4 s,使用記憶體最多約為 3.5 MB,通過測試。 ```cpp= #include <iostream> #include <vector> #include <utility> // for pair #include <algorithm> // for upper_bound using namespace std; int main() { int n; cin >> n; // 讀取數量 n vector<pair<int, int>> fruit (n, {0, 0}); // 儲存果實位置的陣列 for(int i=0; i<n; i++) cin >> fruit[i].first >> fruit[i].second; // 讀取 n 行資料,組成 pair,加到 fruit sort(fruit.begin(), fruit.end()); // 依照果實 x 座標由小到大排序 vector<int> st; // 果實 y 座標要遞增 for(auto f : fruit) { // 依序由 fruit 讀取資料 if (st.empty() || f.second >= st.back()) st.push_back(f.second); // 如果 st 是空的或 y 大於等於 st.back(),找到新的果實,加到 st else st[upper_bound(st.begin(), st.end(), f.second) - st.begin()] = f.second; // 否則用 upper_bound 找到於 st 中插入 y 的右側位置,重設值為 y } cout << st.size() << "\n"; // st 的長度就是答案 return 0; } ``` <br /><br /> --- ###### tags:`APCS`、`Python`、`C++`