Shopaholic
每組送最便宜的那件,所以貴的要跟貴的湊一組;降序排序後取第 3、6、9… 個,貴的即為答案。
| Attempts | 3 |
|---|---|
| First attempt | 2026-09-14 |
| Solved | 2026-09-21 |
Problem
題目說 Lindsay 是個購物狂。只要看到「買三付二」的優惠(帶三件去結帳、只付兩件的錢),她就會失控地想把整間店買下來。你治不好她的強迫性購物症,不過卻能想辦法幫她的錢包止血(嗎?)
規則的關鍵有兩點:
-
結帳時店家會把商品每 3 件分成一組,然後送掉每組裡最便宜的那一件。
-
不過店家允許 Lindsay 可以分很多次結帳,而且自己決定每次帶哪些商品,也就是說結帳前可以精打細算來最大化折扣的總金額!
然後題目最後要問的是:你最多能幫 Lindsay 省下多少錢?
輸入第一行是測資組數 ,每組測資兩行:商品數 ,以及 個價格。限制為 、、。
Approach
每組送掉的是最便宜的那件,因此如果要讓折扣金額變大,就要讓每組的最小值盡量大。
反過來想更清楚:如果把一件貴的商品跟兩件便宜的湊一組,那件貴的就只是在湊人數,送出去的卻是便宜貨,它的價值被浪費了。所以正確做法是由大到小排序,每 3 件切一組。
整題就化約成一句話:降序排好後,把 arr[2]、arr[5]、arr[8]… 加起來就是答案。
Wrong attempts
我第一次是升序排序,然後想「起點要看 的奇偶」:
sort(arr, arr + n);
bool is_even = false;if (n % 2 == 0) { is_even = true;}
if (is_even) { for (int j = 0; j < n; j += 3) { if (arr[j] == 0) break; max_discount += arr[j]; }} else { for (int j = 1; j < n; j += 3) { if (arr[j] == 0) break; max_discount += arr[j]; }}錯在決定起點的是 ,不是 。
升序陣列裡免費的是 index 一路往回走,走到最小的那個下標就是 。所以升序版的正確寫法只有一行:
bool is_even = (n % 2 == 0);for (int j = (is_even ? 0 : 1); j < n; j += 3)for (int j = n % 3; j < n; j += 3) max_discount += arr[j];奇偶判斷只在某些 剛好對上,這就是為什麼它能通過我手上的測資:
| (正確起點) | 我的起點(奇偶) | 結果 | |
|---|---|---|---|
| 6 | 0 | 0(偶) | ✅ 巧合 |
| 7 | 1 | 1(奇) | ✅ 巧合 |
| 4 | 1 | 0(偶) | ❌ |
| 5 | 2 | 1(奇) | ❌ |
| 8 | 2 | 0(偶) | ❌ |
官方 sample 是 、題敘的例子是 ,兩筆都剛好巧合。我只拿這兩組測,所以當然測不出來就 WA 了。
Solution
想通之後改成降序排序、從 index 2 起跳每次加 3,一次就過了。
6 collapsed lines
#include <iostream>#include <algorithm>#include <functional> // greater<int>
using namespace std;
void solve() { int t, n; int arr[20005] = {0};
cin >> t; while (t--) { cin >> n; for (int j = 0; j < n; j++) cin >> arr[j];
sort(arr, arr + n, greater<int>());
int max_discount = 0; for (int j = 2; j < n; j += 3) { max_discount += arr[j]; }
cout << max_discount << '\n'; }}
8 collapsed lines
int main() { ios::sync_with_stdio(false); cin.tie(nullptr);
solve();
return 0;}被標起來的四行就是全部的演算法:排序,然後從 開始每次跳 3 格。
Sample Input
16400 100 200 350 300 250Sample Output
400驗算:排序後是 ,取 index 2 和 5 得 ,答案正確。
錯誤歷程
- WA用 n % 2 判斷升序起點,只拿題目範例驗證#1
- WA同樣的奇偶邏輯,改了細節但還是錯#2
- AC改成降序排序,每 3 個取第 3 個,自己多測了幾個測資#3