開啟章節選單
10626 Buying Coke
題目連結
題目敘述
我經常在公司裡的自動販賣機買可樂
通常我一次會買好幾瓶,因為我的同事們也喜歡喝可樂
自動販賣機上的一瓶可樂售價為 8 瑞典克朗
且機器只接受面額為 1、5 和 10 的硬幣
當我按下可樂的按鈕(在投入足夠的錢之後)時
我會先得到一瓶可樂,再拿到零錢(如果有的話)
零錢總是以最少硬幣數量找回(由於硬幣面額固定,此方式下找零方式唯一)
這個過程會重複,直到我買完所有想要的可樂
請注意,我可以將拿到的零錢重投入機器以購買後續的可樂
現在,給定我想買的可樂數量,以及我手上各面額硬幣的數量
問我至少需要投入多少硬幣?假設販賣機永遠不會缺硬幣
而且我手上的錢總額足以買完所有的可樂
輸入格式
- 第一行包含測試資料組數目 T(T ≤ 50)。
- 接下來每組資料各佔一行,包含四個整數:
- C:想買的可樂數量(1 ≤ C ≤ 150)
- n₁:1 元硬幣的數量(0 ≤ n₁ ≤ 500)
- n₅:5 元硬幣的數量(0 ≤ n₅ ≤ 100)
- n₁₀:10 元硬幣的數量(0 ≤ n₁₀ ≤ 50)
輸出格式
對於每組測試資料,在一行上輸出一個整數:投入機器的最少硬幣數量。
解題思路
此題有兩種解法分為
- 貪心(較快)
- 遞迴枚舉 + 記憶化搜索(較慢)
-
貪心
-
遞迴枚舉 + 記憶化搜索
狀態以 a, b, c 表示當前手上有 a 枚 1 元、b 枚 5 元、c 枚 10 元
分別對五種條件進行遞迴枚舉
- 用 10 元,找回 2×1,成本 1
- 用 10+3×1,找回 5+2×1(等價於先用 10,找 2 1,再用 3 1),成本 4
- 用 2×5,找回 2×1,成本 2
- 用 5+3×1,不找零,成本 4
- 用 8×1,不找零,成本 8
結束條件為 剩餘硬幣的金額
等於 初始金額 - 購買所有可樂所需的金額
並搭配記憶化搜索以避免重複計算
程式碼
- 貪心
#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() ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL) #define all(x) (x).begin(), (x).end() #define int long long #define PII pair<int, int> signed main() { WA(); int t; cin >> t; while (t--) { int n, c1, c5, c10, ans = 0; cin >> n >> c1 >> c5 >> c10; if (c10 >= n) cout << c10; else { n -= c10; if (c5 >= n*2) cout << c10 + n*2; else if (c5 >= n) cout << c10 + 6*n - 2*c5; else if (c10 >= n - c5) cout << c10 + 2*n - 2*c5; else cout << 8*n + 4*c5; } cout << '\n'; } }
- 遞迴枚舉 + 記憶化搜索
#include <bits/stdc++.h> using namespace std; int k, dp[800][300][100]; int dfs(int a, int b, int c) { if (k == a + b*5 + c*10) return 0; int &N = dp[a][b][c]; if (N) return k; N = INF; if (c > 0) N = min(N, dfs(a+2, b, c-1) + 1); if (c > 0 && a >= 3) N = min(N, dfs(a-3, b+1, c-1) + 4); if (b >= 2) N = min(N, dfs(a+2, b-2, c) + 2); if (b > 0 && a >= 3) N = min(N, dfs(a-3, b-1, c) + 4); if (a >= 8) N = min(N, dfs(a-8, b, c) + 8); return N; } int main() { int t, n, a, b, c; cin >> t; while (t--) { cin >> n >> a >> b >> c; k = a + b*5 + c*10 - n*8; memset(dp, 0, sizeof(dp)); cout << dfs(a, b, c) << '\n'; } }