设有 n 种不同面值的硬币,各硬币的面值存于数组 T[1:n]中。现要用这些 面值的硬币来找钱。可以使用的各种面值的硬币个数存于数组 Coins[1:n]中。 对任意钱数 0≤m≤20001,设计一个用最少硬币找钱 m 的方法。 输入: 输入的第一行中只有 1 个整数给出 n 的值,第 2 行起每行 2 个数,分别 是 T[j]和 Coins[j]。最后 1 行是要找的钱数 m。 输出: 程序运行结束时,将计算出的最少硬币数输出。问题无解时输出-1。除了输出最少硬币个数,还输出每种面额的硬币各用了多少个。
时间: 2024-02-18 07:03:47 浏览: 64
以下是使用动态规划算法解决该问题的 Python 代码实现:
```python
n = int(input())
T = list(map(int, input().split()))
Coins = list(map(int, input().split()))
m = int(input())
# 初始化dp数组
dp = [float("inf")] * (m + 1)
dp[0] = 0
# 逐个计算dp[i]
for i in range(n):
for j in range(m, T[i]-1, -1):
# 如果当前面值的硬币数量不为0且可以凑出j
if Coins[i] > 0 and dp[j-T[i]] < float("inf"):
dp[j] = min(dp[j], dp[j-T[i]] + 1)
Coins[i] -= 1
# 输出结果
if dp[m] == float("inf"):
print(-1)
else:
print(dp[m])
for i in range(n):
cnt = 0
for j in range(1, dp[m]+1):
if dp[m-j*T[i]] == dp[m] - j:
cnt += 1
print(T[i], cnt)
```
算法思路:
设 dp[i] 表示凑出钱数为 i 所需要的最少硬币数,则有:
dp[i] = min(dp[i], dp[i-T[j]]+1)
其中 T[j] 表示第 j 种面值的硬币。
注意,为了避免重复使用同一种面值的硬币,我们需要在计算 dp[i] 的时候,从大到小遍历硬币面值,同时在计算 dp[i-T[j]] 的时候,需要先判断 Coins[j] 是否为 0,如果为 0,则说明该面值的硬币已经用完了,不能再使用。
最后,如果 dp[m] 为无穷大,则说明无法凑出钱数 m,输出 -1;否则,输出 dp[m],并根据 dp 数组反推每种面值的硬币使用数量。
阅读全文