算法第37天| 完全背包\518. 零钱兑换 II\377. 组合总和 Ⅳ\57. 爬楼梯

完全背包

完全背包和01背包的区别

纯完全背包 ,遍历背包和物品的顺序是可以对调的,只要求得出最大价值,不要求凑成总和的元素的顺序;
01背包 ,遍历背包和物品的顺序是不可以对调的(一维不行,二维是可以的);

一维解法中 遍历顺序 主要就是用来保证物品 不被重复使用 的,而完全背包中物品本身就是可以重复使用的,所以就无所谓了。

完全背包

题目

思路与解法

cpp 复制代码
#include <iostream>
#include <vector>
using namespace std;

int main(){

    int n; // 物品种类
    int v; // 背包大小
    cin >> n >> v;

    vector<int> weight(n, 0); // 物品重量
    vector<int> value(n, 0); // 物品价值

    for(int i=0;i<n;i++){
        cin >> weight[i] >> value[i];
    }

    // for(int i=0;i<n;i++){
    //     cout<< weight[i];
    //     cout<< value[i]<<" ";
    // }

    // dp数组含义:
    //  dp[i]: 背包容量为i时,放入小于等于当前序号的物品所能达到的最大价值
    vector<int> dp(v+1, 0);

    // 先遍历 物品
    for(int i=0;i<n;i++){
        // 后遍历 背包
        for(int j=weight[i];j<=v;j++){
            dp[j] = max(dp[j-weight[i]]+value[i], dp[j]);
        }
    }

    cout << dp[v] << endl;

    return 0;
}

518. 零钱兑换 II

题目

思路与解法

cpp 复制代码
class Solution {
public:
    int change(int amount, vector<int>& coins) {
        // dp数组含义:
        //  dp[i]: 总金额为i时,使用小于大于当前硬币序号的硬币能凑成总金额的方式总数
        vector<uint64_t> dp(amount+1, 0);
        dp[0] = 1;

        // 先遍历 物品
        for(int i=0;i< coins.size();i++){
            for(int j = coins[i];j <= amount;j++){
                dp[j] += dp[j-coins[i]];
            }
        }

        return dp[amount];
    }
};

377. 组合总和 Ⅳ

题目

思路与解法

python 复制代码
class Solution {
public:
    int combinationSum4(vector<int>& nums, int target) {
        //dp数组含义:组合的个数
        vector<uint64_t> dp(target+1, 0);
        dp[0] = 1;

        //先背包再物品 因为求的是排列
        for(int i=0;i<=target;i++){
            for(int j=0;j<nums.size();j++){
                if(nums[j] <= i) dp[i] += dp[i-nums[j]];
            }
        }

        return dp[target];
    }
};

57. 爬楼梯(第八期模拟笔试)

题目

思路与解法

cpp 复制代码
 #include<iostream>
 #include <vector>
 using namespace std;

 int main(){
    int n, m; //n:总数,m:步长范围
    cin >> n >> m;

    // dp数组含义:
    //  方式总数
    vector<int> dp(n+1, 0);
    dp[0] = 1;

    // 先背包再物品 因为求的是排列
    // 反过来就是求组合
    for(int i = 0;i<=n;i++){
        for(int j = 1;j<=m;j++){
            if(j <= i) dp[i] += dp[i-j]; 
        }
    }

    cout << dp[n] << endl;

    return 0;
 }