代码随想录第32天|
多重背包:
#include<bits/stdc++.h>
using namespace std;
int main() {int C,N;cin>>C>>N;int weight[10002];int price[10002];int num[10002];for(int i=0;i<N;i++){for(int j=0;j<3;j++){cin>>weight[j]>>price[j]>>num[j];}}int dp[10003];for(int i=0;i<N;i++){for(int j=weight[i];j<=C;j++){//对于每一个物品进行遍历for(int k=1;k<=nums[i]&&(j-k*weight[i])>=0;k++){dp[j]=max(dp[j],dp[j-k*weight[i]]+k*price[i]);}}}return dp[C];
}
打家劫舍系列:
class Solution {
public:int rob(vector<int>& nums) {int dp[102]={0};//代表偷前i个房屋最多能偷多少钱dp[0]=nums[0];for(int i=1;i<nums.size();i++){if(i>=2){dp[i]=max(dp[i-1],dp[i-2]+nums[i]);}else{dp[i]=max(dp[i-1],nums[i]);}}return dp[nums.size()-1];}
};
// 注意注释中的情况二情况三,以及把198.打家劫舍的代码抽离出来了
class Solution {
public:int rob(vector<int>& nums) {if (nums.size() == 0) return 0;if (nums.size() == 1) return nums[0];int result1 = robRange(nums, 0, nums.size() - 2); // 情况二int result2 = robRange(nums, 1, nums.size() - 1); // 情况三return max(result1, result2);}// 198.打家劫舍的逻辑int robRange(vector<int>& nums, int start, int end) {if (end == start) return nums[start];vector<int> dp(nums.size());dp[start] = nums[start];dp[start + 1] = max(nums[start], nums[start + 1]);for (int i = start + 2; i <= end; i++) {dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]);}return dp[end];}
};
原理就是:假如你考虑第一个元素就不能选最后一个 你考虑最后一个元素就不能选第一个两种情况动态规划求最大值
树状数组:重点在于定义 当前节点的含义:下标为0记录不偷该节点所得到的的最大金钱,下标为1记录偷该节点所得到的的最大金钱。
class Solution {
public:int rob(TreeNode* root) {vector<int> result = robTree(root);return max(result[0], result[1]);}// 长度为2的数组,0:不偷,1:偷vector<int> robTree(TreeNode* cur) {if (cur == NULL) return vector<int>{0, 0};vector<int> left = robTree(cur->left);vector<int> right = robTree(cur->right);// 偷cur,那么就不能偷左右节点。int val1 = cur->val + left[0] + right[0];// 不偷cur,那么可以偷也可以不偷左右节点,则取较大的情况int val2 = max(left[0], left[1]) + max(right[0], right[1]);return {val2, val1};}
};