题目
题目链接
解题思路
这是一个完全背包问题的变种,求组合数。关键点:
-
状态定义:
- \(dp[i]\) 表示组成金额 \(i\) 的方案数
-
状态转移:
- \(dp[i] += dp[i - coin]\)
- 对每个面值 \(coin\),更新所有可能的金额 \(i\)
-
边界条件:
- \(dp[0] = 1\),表示金额为 \(0\) 时有 \(1\) 种方案(什么都不选)
- 金额为负数时方案数为 \(0\)
代码
class Exchange {
public:int countWays(vector<int>& changes, int n, int x) {vector<int> dp(x + 1, 0);dp[0] = 1; // 初始化,金额为0时有1种方案// 遍历每种面值for(int coin : changes) {// 更新所有可能的金额for(int i = coin; i <= x; i++) {dp[i] += dp[i - coin];}}return dp[x];}
};
import java.util.*;public class Exchange {public int countWays(int[] changes, int n, int x) {int[] dp = new int[x + 1];dp[0] = 1; // 初始化,金额为0时有1种方案// 遍历每种面值for(int coin : changes) {// 更新所有可能的金额for(int i = coin; i <= x; i++) {dp[i] += dp[i - coin];}}return dp[x];}
}
# -*- coding:utf-8 -*-
class Exchange:def countWays(self, changes, n, x):dp = [0] * (x + 1)dp[0] = 1for coin in changes:for i in xrange(coin, x + 1):dp[i] += dp[i - coin]return dp[x]
算法及复杂度
- 算法:动态规划(完全背包)
- 时间复杂度:\(\mathcal{O(nx)}\),其中 \(n\) 为零钱种类数,\(x\) 为目标金额
- 空间复杂度:\(\mathcal{O(x)}\),需要一个长度为x+1的dp数组