设有 n 种不同面值的硬币,各硬币的面值存于数组 T[1:n]中。现要用这些 面值的硬币来找钱。可以使用的各种面值的硬币个数存于数组 Coins[1:n]中。 对任意钱数 0≤m≤20001,设计一个用最少硬币找钱 m 的方法。 输入: 输入的第一行中只有 1 个整数给出 n 的值,第 2 行起每行 2 个数,分别 是 T[j]和 Coins[j]。最后 1 行是要找的钱数 m。 输出: 程序运行结束时,将计算出的最少硬币数输出。问题无解时输出-1 除了输出最少硬币个数,还输出每种面额的硬币各用了多少个。
时间: 2024-03-05 17:55:07 浏览: 71
这是一个比较典型的动态规划问题。我们可以使用一个一维数组 dp 来保存每个钱数所需要的最少硬币数。初始化 dp[0] = 0,其余 dp[i] = INF(表示无限大)。
然后,我们对于每个面值 T[j],枚举 0≤k≤m-T[j],并更新 dp[k+T[j]] = min(dp[k+T[j]], dp[k]+1),即使用了一枚 T[j] 面值的硬币,钱数增加 T[j],所需硬币数加 1。
最终,dp[m] 即为所求的最少硬币数。如果 dp[m] 仍然是 INF,则说明无解。
同时,我们可以记录每种面额的硬币各用了多少个,具体方法是,在更新 dp[k+T[j]] 时,如果 dp[k+T[j]] 被更新了,则说明用了一枚 T[j] 面值的硬币,将 Coins[j]-1,并记录这个操作。最后输出每种面额的硬币各用了多少个即可。
下面是完整的代码实现:
```matlab
n = input('请输入硬币种数:');
T = zeros(1, n);
Coins = zeros(1, n);
for i = 1:n
T(i) = input('请输入硬币面值:');
Coins(i) = input('请输入硬币个数:');
end
m = input('请输入要找的钱数:');
INF = 1000000000; % 表示无限大
dp = INF * ones(1, m+1);
dp(1) = 0;
used = zeros(1, n);
for i = 1:n
for j = 0:m-T(i)
if dp(j+1) < INF && Coins(i) > 0
if dp(j+T(i)+1) > dp(j+1)+1
dp(j+T(i)+1) = dp(j+1) + 1;
used(i) = used(i) + 1;
Coins(i) = Coins(i) - 1;
end
end
end
end
if dp(m+1) == INF
fprintf('无解\n');
else
fprintf('最少硬币数:%d\n', dp(m+1));
fprintf('每种面额的硬币各用了多少个:\n');
for i = 1:n
fprintf('%d元硬币:%d个\n', T(i), used(i));
end
end
```
需要注意的是,这里的 dp 数组下标从 1 开始,因此在更新 dp[k+T[j]] 时,要将 j 和 k 都加 1。
阅读全文