day44|● 完全背包● 518. 零钱兑换 II ● 377. 组合总和 Ⅳ

518. 零钱兑换 II

1.代码

class Solution {
public:
    int change(int amount, vector& coins) {
         vectorf(amount + 1, 0);
         f[0] = 1;
         for (int i = 0; i < coins.size(); i++) {
             for (int j = coins[i]; j <= amount; j++) {
                 f[j] += f[j - coins[i]];
             }
         }
         return f[amount];
    }
};

2.动规五部曲

1.确定dp数组和其下标含义

由题目说可知求选择钱票得到总和为target的方案数,dp[j]相当于选择物品体积相加为i的方案数

2.递推公式

每次加入物品,都有可能到达体积j,所以在每次加上这个物品到达j时加上这个方案数

f[j] += f[j - coins[i]];

3.初始化

因为在for循环和dp公式中没有确切的值,肯定需要初始化,初始化第一个就可以保证后面的推导出来了,f[0]=1,代表背包为0时的方案数为1,说明不选任何东西

4.确定遍历顺序

第一层for循环就是选取每个物品,第二层循环也为正序,因为需要重复选取,正序就能用到之前的背包了,所以可以重复选取,第二层就是遍历每一个不同大小的背包来装每一个物品进行筛选。

5.举例说明dp数组


377. 组合总和 Ⅳ

1.代码

class Solution {
public:
    int combinationSum4(vector& nums, int target) {
        vectorf(target + 1, 0);
        f[0] = 1;
        for (int i = 0; i <= target; i++) {
            for (int j = 0; j < nums.size(); j++) {
                if (i >= nums[j] && f[i] < INT_MAX - f[i - nums[j]]) f[i] += f[i - nums[j]];
            }
        }
        return f[target];
    }
};

1.动规五部曲

4.确定遍历顺序

因为是求排列数,不是组合数,说明不一样的顺序也可以,如果物品放到里面时,外面的每个背包都可以进行物品筛选,所以两层for循环需要反过来顺序

如果求组合数就是外层for循环遍历物品,内层for遍历背包

如果求排列数就是外层for遍历背包,内层for循环遍历物品

 第一层遍历背包,第二层遍历物品,因为顺序翻过来了 ,那么不能在for循环中增加判断条件。在for循环外加if就行了,还需要确保超过int最大范围

5.模拟

你可能感兴趣的:(代码随想录一刷,算法,leetcode,c++,动态规划,数据结构)