代码随想录算法训练营第四十六天
KM52. 携带研究材料
题目链接:KM52. 携带研究材料
- 确定dp数组以及下标的含义:j的含义是当前背包的最大容量,dp[j]背包内物品的总价值
- 确定递推公式:背包最大容量固定为j,每个循环尝试在当前最大容量下,把物品往背包里试着放一下,面临2种情况:
- 最大容量不够放入当前选择的物品,背包内最大的价值就是原来的dp[j],
- 最大容量能放下当前选择的物品,价值为dp[j-wights[i]]+values[i],将wights[i]这么多空间价值的物品取出,在把当前物品的价值放进去的总价值,或者不进行这个交换的总价值哪个更大
- dp数组如何初始化:背包容量为0,没法放物品,价值就都是0,
- 确定遍历顺序:完全背包:从小到大,表示可以把同一物品放进背包多次。01背包:从大到小,表示每个物品只能放一次。
- 打印dp数组。
#include <iostream>
#include <vector>using namespace std;
int main(){int N;int V;cin >>N>>V ;vector<int> wights(N);vector<int> values(N);for(int i = 0;i<N;i++){cin>>wights[i]>>values[i];}vector<int>dp(V+1);for(int i = 0;i<N;i++){for(int j = wights[i];j<=V;j++)dp[j] = max(dp[j],dp[j-wights[i]]+values[i]);}cout<<dp[V];return 0;
};
518. 零钱兑换 II
题目链接:518. 零钱兑换 II
- 确定dp数组以及下标的含义:j为背包的最大容量,dp[j]当容量为j有几种组合方式
- 确定递推公式:dp[j]=dp[j]+dp[j-nums[i]],不放当前数字组成目标值的种类+必须放当前数字组成目标值的种类(为了保证一定放这个值,就要把需要的容量腾出来)
- dp数组如何初始化:容量为0,有一种放法,dp[0] = 1;
- 确定遍历顺序:先遍历物品,再遍历背包容量,求出来的是组合种类;先遍历背包容量再变量物品,求出来每个容量下不同物品排列的种类数。本题属于前者。
- 打印dp数组。
class Solution {
public:int change(int amount, vector<int>& coins) {vector<int>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. 组合总和 Ⅳ
题目链接:377. 组合总和 Ⅳ
- 确定dp数组以及下标的含义:j为背包的最大容量,dp[j]当容量为j有几种组合方式
- 确定递推公式:dp[j]=dp[j]+dp[j-nums[i]],不放当前数字组成目标值的种类+必须放当前数字组成目标值的种类(为了保证一定放这个值,就要把需要的容量腾出来)
- dp数组如何初始化:容量为0,有一种放法,dp[0] = 1;
- 确定遍历顺序:先遍历物品,再遍历背包容量,求出来的是组合种类;先遍历背包容量再变量物品,求出来每个容量下不同物品排列的种类数。本题属于后者。
- 打印dp数组。
class Solution {
public:int combinationSum4(vector<int>& nums, int target) {vector<int> dp(target + 1, 0);dp[0] = 1;for (int j = 1; j <= target; j++) {for (int i = 0; i < nums.size(); i++) {if (j >= nums[i] && dp[j] < INT_MAX - dp[j - nums[i]]) {dp[j] += dp[j - nums[i]];}}}return dp[target];}
};