//二维dp数组做法#include<bits/stdc++.h>usingnamespace std;intmain(){//m为材料种类数,n为行李箱最大空间数int m, n;cin >> m >> n;//room数组存储m种材料所占的体积vector<int>room(m,0);for(int i =0; i < m; i++)cin >> room[i];//value数组存储m种材料所占的价值vector<int>value(m,0);for(int i =0; i < m; i++)cin >> value[i];//1确定动态规划dp数组及其下标含义,这里指第(1, m)种材料(对应索引0,m-1)在占用(0, n)体积时的价值vector<vector<int>>dp(m,vector<int>(n+1,0));//3初始化,存储第一种材料的价值,背包体积大于room[0]时,背包的价值为value[0]//下面是两种初始化方法for(int i = room[0]; i <= n; i++){dp[0][i]= value[0];}// for(int i = 1; i < n; i++)// {// if(room[0] <= i)// dp[0][i] = value[0];// }//2确定递推公式 4 确定递推遍历顺序for(int i =1; i < m; i++){for(int j =1; j <= n; j++){//当背包体积不够时,不装第i种材料,此时最大价值为dp[i-1][j]背包的价值if(room[i]> j)dp[i][j]= dp[i-1][j];//当背包体积够时,取价值最大值,不装第i种材料的价值,装第i种材料的价值+背包剩余体积装材料的最大价值elsedp[i][j]=max(dp[i-1][j],dp[i-1][j-room[i]]+value[i]);}}//dp[m-1][n]表示m种材料装在n体积背包的最大价值cout << dp[m-1][n]<< endl;return0;}
//一维dp数组做法(滚动数组)#include<bits/stdc++.h>usingnamespace std;intmain(){//m为材料种类数,n为行李箱最大空间数int m, n;cin >> m >> n;//room数组存储m种材料所占的体积vector<int>room(m,0);for(int i =0; i < m; i++)cin >> room[i];//value数组存储m种材料所占的价值vector<int>value(m,0);for(int i =0; i < m; i++)cin >> value[i];//1确定动态规划dp数组及其下标含义,这里指占用[0, n]体积时的价值vector<int>dp(n+1,0);//3初始化,存储第一种材料的价值,背包体积大于room[0]时,背包的价值为value[0]//2确定递推公式 4 确定递推遍历顺序//遍历m种材料for(int i =0; i < m; i++){//倒序遍历[room[i], j]体积下的最大价值//不能用正序遍历,否则dp[2]会重复dp[1]for(int j = n; j >= room[i]; j--){//递推公式,取两者最大值//dp[j](前面遍历的该体积下的最大价值),//dp[j-room[i]]+value[i],j-room[j]空间大小下的最大价值+第i种材料的价值dp[j]=max(dp[j], dp[j-room[i]]+value[i]);}}//dp[n]表示n体积背包的最大价值cout << dp[n]<< endl;return0;}
LeetCode 416 分割等和数组 2023.12.6
题目链接
代码随想录讲解[链接]
boolcanPartition(vector<int>& nums){//sum存储nums数组的总和int sum =0;// for (int i = 0; i < nums.size(); i++)// sum += nums[i];//求和或拼接函数(迭代器,迭代器,累加值i),sum=数组和+isum =accumulate(nums.begin(), nums.end(),0);cout << sum << endl;//先判断和是否为偶数,如果不是则不能分为两个等和数组,直接返回falseif(sum%2==1)returnfalse;//和为偶数时,两个等和数组的和目标值为一半和int target = sum/2;//1确定dp数组,其下标含义为当前背包下的最大子数组和,3初始化元素都为0//因为数组元素最大值100,数组大小最大为100,那么最大target为10000vector<int>dp(10001,0);//2确定递推公式,4确定遍历顺序,数组中每个元素只使用一次,那么倒序遍历for(int i =0; i < nums.size(); i++){//j为背包的大小,需要大于当前遍历值for(int j = target; j >= nums[i]; j--)//取极大值:判断之前遍历的元素在背包j值时的最大元素和与加入该值后的最大元素和dp[j]=max(dp[j], dp[j-nums[i]]+nums[i]);}//最终判断条件,在能存储数值为target的背包内值为target时,说明能分为两个等和数组if(dp[target]== target)returntrue;returnfalse;}
LeetCode 1049 最后一块石头的重量-ii 2023.12.6
题目链接
代码随想录讲解[链接]
intlastStoneWeightII(vector<int>& stones){//sum存储石头总重量int sum =accumulate(stones.begin(), stones.end(),0);//target存储一半石头总重量,当总重量为奇数时,2*target<sumint target = sum/2;//1确定dp数组,其下标含义为能存储重量为i的背包最大能存储石头重量//本题中想把石头分为重量相同或者相近的两堆,这样最后剩下的石头重量为0或者最小//3初始化元素均为0vector<int>dp(target+1,0);//2确定递推公式,4确定遍历顺序//计算重量为i的背包最大能存储石头重量,每块石头只能用一次所以倒序遍历for(int i =0; i < stones.size(); i++){//j为背包的大小,需要大于当前遍历重量值for(int j = target; j >= stones[i]; j--)//取极大值:判断之前遍历的元素在背包j值时的最大重量和与加入该重量值后的最大重量和dp[j]=max(dp[j], dp[j-stones[i]]+stones[i]);}//能存储target一半总重量的背包最多能存储target重量或者更少//sum-dp[target]为另一堆更多的重量,减掉dp[target]即为最小重量;相同时答案为0return sum - dp[target]- dp[target];}