搜索
您的当前位置:首页正文

dp完全背包问题解组合问题——零钱兑换

来源:意榕旅游网

class Solution {
public:
   int change(int amount, vector<int>& coins) {
        // 完全背包  顺序遍历
        // 背包容量为amount
        int n = coins.size();
        // dp[i][j]:有coin[0]...coin[i]这i+1个硬币,凑出amount,有dp[i][j]种方法
        vector<vector<int>> dp(n, vector<int>(amount + 1, 0));
        dp[0][0] = 1;
        for(int j = 1; j <= amount; j++){
            // 只有coins[0]一枚硬币,若能整除,则只有1种方法凑出j,若不能整除,则不能凑出j
            dp[0][j] = (j % coins[0] == 0) ? 1 : 0;
        }
        // 遍历硬币
        for(int i = 1; i < n; i++){
            // 遍历面值
            for(int j = 0; j <= amount; j++){
                if(j < coins[i]){
                    // 当前面值 < 当前硬币,无法使用当前硬币,依然使用前0~i-1种硬币凑出面值j
                    dp[i][j] = dp[i-1][j];
                }else{
                    // 当前面值 >= 当前硬币
                    // dp[i-1][j]表示不使用当前硬币凑出j的方法数
                    // dp[i][j-coins[i]]则表示使用至少使用一枚coins[i]硬币凑出j,完全背包,使用本层计算结果
                    // 这里不能是dp[i-1][j-coins[i]],因为这表示只使用一枚coins[i]凑出面值j
                    dp[i][j] = dp[i-1][j] + dp[i][j-coins[i]];
                }
            }
        }
        return dp[n-1][amount];
    }
};
class Solution {
public:
    int change(int amount, vector<int>& coins) {
        // 完全背包  顺序遍历
        // 背包容量为amount
        int n = coins.size();
        // dp[j]:使用前i钟货币凑出j,有dp[j]种方法
        vector<int> dp(amount + 1, 0);
        dp[0] = 1;
        // 遍历硬币
        for(int i = 0; i < n; i++){
            // 遍历面值
            for(int j = coins[i]; j <= amount; j++){
                dp[j] = dp[j] + dp[j-coins[i]];
            }
        }
        return dp[amount];
    }
};

class Solution {
public:
	int coinChange(vector<int>& coins, int amount) {
        // 完全背包---> 顺序
        // 组合 ---> 先遍历物品
        vector<int> dp(amount + 1, amount + 1);
        dp[0] = 0;
        for(int i = 0; i < coins.size(); i++){
            for(int j = coins[i]; j <= amount; j++){
            	// 不使用coins[i],使用coins[i]
            	// 用dp[j-coins[i]]个硬币凑出j-coins[i],再用1个coins[i]凑出coins[i]
            	// dp[j-coins[i]]在二维数组中使用的是本层数据,表示使用0...i种货币凑出j-coins[i],再用1个coins[i]凑出coins[i]
            	// 这样dp[j-coins[i]]+1就能表示至少使用1个coins[i],凑出j,所需要的货币数量
                dp[j] = min(dp[j], dp[j-coins[i]] + 1); 
            }
        }
        return dp[amount] > amount ? -1 : dp[amount];
    }
};

因篇幅问题不能全部显示,请点此查看更多更全内容

Top