---
###### tags: `2021 師大附中資訊科暑期培訓`
---
# 貪心法
2021 師大附中資訊科暑期培訓
joylintp
---
## 每次選擇對當前狀態最有利的決策
---
## 換硬幣
有 50、10、5、1 四種面額的硬幣,
求至少要多少硬幣才能湊出總額 $k$ 元
----
* 先盡量用 50 元湊
* 剩下的部分盡量用 10 元湊
* 剩下的部分盡量用 5 元湊
* 剩下的部分用 1 元湊
----
$ans= \lfloor \frac{k}{50} \rfloor + \lfloor \frac{k\ mod\ 50}{10} \rfloor + \lfloor \frac{k\ mod\ 10}{5} \rfloor + k\ mod\ 5$
---
## Add All
### ZJ d221
有 $N$ 個數字,
每次可以選擇兩個數字將其合併,
並將兩數字的總和放回序列,
合併所需的成本為兩個數字的總和,
求將所有數字合併成一個的最少總成本為何
----
<u>1 2</u> 3 // cost = 3
→ <u>3 3</u> // cost = 6
→ 6
總成本為 9
----
* 每次選擇最小的兩個數字合併
* 搭配 `priority_queue` 維護最小的兩個數
----
```cpp=
priority_queue<int, vector<int>, greater<int>> pq;
for (int i : arr)
pq.push(i);
int ans = 0;
while (pq.size() > 1)
{
int t = pq.top();
pq.pop(), t += pq.top(), pq.pop();
pq.push(t), ans += t;
}
```
時間複雜度 $O(N\log{N})$
---
## 乘船問題
有 $N$ 個人,第 $i$ 個人體重為 $W_i$
每艘船的限重皆為 $K$,且最多只能乘載兩人
問至少需要幾艘船才能乘載所有人
----
$N = 5,\ K = 6$
$W = [1, 4, 3, 2, 6]$
→ $[1, 3],\ [2, 4],\ [6]$
----
考慮尚未上船的體重最輕的人 $i$:
* 若剩餘所有人的體重皆超過 $K - W_i$,
則剩下所有人皆一人一艘船
* 否則 $i$ 與體重不超過 $K - W_i$ 的最重的人
坐同一艘船
----
```cpp=
multiset<int> ms;
for (int i : W)
ms.insert(i);
int ans = 0;
while (!ms.empty())
{
int Wi = *ms.begin();
ms.erase(ms.begin());
ans++;
auto p = ms.upper_bound(K - Wi);
if (p != ms.begin())
ms.erase(prev(p));
else
{
ans += ms.size();
break;
}
}
```
時間複雜度 $O(N\log{N})$
---
## 更多 Greedy
### ZJ a465 (UVa 12405): Scarecrow
### Sprout OJ 91 (UVa 993): 調校高棕櫚!
### Sprout OJ 89 (NPSC 2005): 誰先晚餐
### Sprout OJ 78 (UVa 311): 包裝禮物
{"metaMigratedAt":"2023-06-15T11:47:53.891Z","metaMigratedFrom":"Content","title":"貪心法","breaks":true,"contributors":"[{\"id\":\"6b95215f-91a7-4eaf-bcfe-d43740108f96\",\"add\":1771,\"del\":161}]"}