uva 674 Coin Change

本文探讨了使用动态规划解决面额组合找零问题的方法,重点介绍了状态表示、状态转移方程及AC代码实现。通过实例演示,展示了如何利用有限的面额组合实现最大找零方案数。
【题意】给你一个面值n,你能通过用1,5,10,25,50这5种面值来找零,问最多的方案数。
【状态表示】dp[i]表示当前需要找零i元的最优方案数。
【状态转移】dp[j]->dp[j+w[i]],0<i<5
【AC代码】
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 8010;
int dp[maxn];
int w[5]={1,5,10,25,50};
int main()
{
    dp[0]=1;
    for(int i=0; i<5; i++)
    {
        for(int j=0; j<maxn-100; j++)
        {
            dp[j+w[i]]+=dp[j];
        }
    }
    int n;
    while(~scanf("%d",&n))
    {
        printf("%d\n",dp[n]);
    }
    return 0;
}

### 功能 `int coinChange(vector<int>& coins, int amount)` 函数的主要功能是解决零钱兑换问题,即给定不同面额的硬币 `coins` 和一个总金额 `amount`,计算出凑成总金额所需的最少硬币个数。若无法凑出总金额,则返回 -1 [^1][^2][^4]。 ### 实现 #### 动态规划实现 ```cpp class Solution { public: int coinChange(vector<int>& coins, int amount) { vector<int> dp(amount + 1, amount + 1); dp[0] = 0; for (int i = 1; i <= amount; i++) { for (int j = 0; j < coins.size(); j++) { if (coins[j] <= i) dp[i] = min(dp[i], dp[i - coins[j]] + 1); } } return dp.back() > amount ? -1 : dp.back(); } }; ``` 上述代码使用动态规划的思想,创建一个长度为 `amount + 1` 的数组 `dp`,`dp[i]` 表示凑成金额 `i` 所需的最少硬币个数。初始化 `dp[0] = 0`,因为凑成金额 0 不需要任何硬币。然后通过两层循环,外层循环遍历金额从 1 到 `amount`,内层循环遍历所有硬币。对于每个硬币,如果其面值小于等于当前金额 `i`,则更新 `dp[i]` 为 `dp[i]` 和 `dp[i - coins[j]] + 1` 中的较小值 [^1][^4]。 #### 回溯 + 剪枝实现 ```cpp class Solution { public: int coinChange(vector<int>& coins, int amount) { if (amount == 0) return 0; int ret = INT_MAX; sort(coins.rbegin(), coins.rend()); coinChange(coins, amount, 0, ret, 0); return ret == INT_MAX ? -1 : ret; } void coinChange(vector<int>& coins, int amount, int count, int &ret, int index) { if (amount == 0) { ret = ret < count ? ret : count; return; } if (index == coins.size()) return; for (int k = amount / coins[index]; k >= 0 && k + count < ret; k--) { coinChange(coins, amount - k * coins[index], count + k, ret, index + 1); } } }; ``` 上述代码采用回溯 + 剪枝的方法,先将硬币从大到小排序,然后从最大面额的硬币开始,尽可能多地使用该硬币,若无法凑出金额则回溯。在回溯过程中,若当前使用的硬币数已经超过当前的最优解 `ret`,则不再向下搜索,进行剪枝 [^3]。 ### 优化方案 - **空间优化**:动态规划的实现中,由于每次状态转移只依赖于前一个状态,因此可以考虑使用滚动数组等方式进一步优化空间复杂度,但在该问题中,由于主要是一维数组,空间优化效果不明显。 - **剪枝优化**:在回溯 + 剪枝的实现中,剪枝策略是关键。可以根据实际情况进一步优化剪枝条件,减少不必要的搜索。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值