給定硬幣面額 {1, 5, 10, 25, 50},求組成金額 n(n ≤ 250)的方案數。每種硬幣可無限使用,但總硬幣數不超過 100 枚。多組輸入,EOF 結束。
二維 DP:dp[i][j] 表示用恰好 j 枚硬幣組成金額 i 的方案數。
初始:dp[0][0] = 1(0 元 0 枚硬幣 1 種方案)。
轉移:對每種硬幣 c,對金額 i 從 c 到 n,對硬幣數 k 從 1 到 100:
dp[i][k] += dp[i - c][k - 1]
最終答案:sum_{k=1}^{100} dp[n][k]。
long long。#include <bits/stdc++.h>
using namespace std;
const int COINS[5] = {1, 5, 10, 25, 50};
const int MAXN = 250, MAXK = 100;
long long dp[MAXN + 1][MAXK + 1];
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
dp[0][0] = 1;
for (int c : COINS) {
for (int i = c; i <= MAXN; ++i) {
for (int k = 1; k <= MAXK; ++k) {
dp[i][k] += dp[i - c][k - 1];
}
}
}
// 預計算前綴和 ans[n] = sum_{k=1}^{100} dp[n][k]
long long ans[MAXN + 1] = {0};
for (int i = 1; i <= MAXN; ++i) {
for (int k = 1; k <= MAXK; ++k) ans[i] += dp[i][k];
}
int n;
while (cin >> n) {
cout << ans[n] << '\n';
}
return 0;
}
這題是經典「帶個數限制的完全背包」變體,二維 DP 狀態設計清晰,預處理思想適用於多測試用例場景。