怎么用C++做硬币问题(DP实现)
时间: 2024-10-03 16:04:25 浏览: 15
硬币找零问题是一个经典的动态规划(DP)问题,通常用于演示递归和记忆化技术的应用。在C++中,我们可以用二维数组或者vector来存储每个状态的最优解,避免重复计算。
以下是基本的步骤:
1. 定义状态:设`dp[i][j]`表示有i元钱,需要找的最大最小组合数,其中`0 <= i <= n`,`n`是硬币面额的最大值。初始条件是`dp[0][0] = 1`,因为没有钱也可以找到0枚硬币。
2. 状态转移方程:对于每一个状态`(i, j)`,如果`j`大于当前的货币`i`,说明无法构成组合,所以`dp[i][j] = 0`;如果`j`等于`i`,说明可以直接用一枚硬币,`dp[i][j] = 1`;否则,我们需要考虑用单个面额小于`j`的所有硬币的组合,即`dp[i][j] = dp[i][j - coins[k]] + dp[i - coins[k]][j]`,这里`coins[]`是所有的硬币面额数组。
3. 代码实现:遍历所有状态,不断更新`dp`数组,最后`dp[n][amount]`就是找零所需的最小硬币组合数,`amount`是要找零的总金额。
```cpp
#include <vector>
using namespace std;
int coinChange(vector<int>& coins, int amount) {
vector<vector<int>> dp(amount + 1, vector<int>(amount + 1, 0));
dp[0][0] = 1;
for (int i = 1; i <= amount; ++i) {
for (int j = 1; j <= i; ++j) {
if (j >= coins[0]) {
dp[i][j] += dp[i - coins[0]][j - coins[0]];
}
for (size_t k = 1; k < coins.size(); ++k) {
if (j >= coins[k]) {
dp[i][j] = max(dp[i][j], dp[i - coins[k]][j]);
}
}
}
}
return dp[amount][amount] ? dp[amount][amount] : -1; // 如果找不到组合返回-1
}
```