1049.最后一块石头的重量II
看完想法:和分割等和子集非常像,主要思想是把石头分成两份重量近似一样的,然后相减,得到的就会是可能的最小数值
int lastStoneWeightII(vector<int>& stones) {vector<int> dp(15000, 0);int sum = 0;for(int i = 0; i< stones.size(); i++){sum+=stones[i];}int bagweight = sum/2;for(int i = 0; i< stones.size(); i++){for(int j = bagweight; j>=stones[i]; j--){dp[j] = max(dp[j], dp[j - stones[i]] + stones[i]);}}return sum - dp[bagweight] - dp[bagweight];}
494.目标和
看完想法:①有两个情况可以直接返回0,target + sum不能向下取整以及target绝对值大于sum
不要纠结初始化的问题,带入 实际情况验证以下
int findTargetSumWays(vector<int>& nums, int target) {int sum = 0;for(int i=0; i< nums.size(); i++) sum+=nums[i];//数组总和int x = (target + sum) / 2;//背包大小//如果背包大小不为整数或者target绝对值大于sum,也不行if((target + sum) %2 ==1 || abs(target) > sum) return 0; vector<int> dp(x+1,0);dp[0] = 1;for(int i = 0; i< nums.size(); i++){for(int j = x; j>=nums[i]; j--){dp[j] +=dp[j - nums[i]];}}return dp[x];
474.一和零
看完想法:虽然需要用两个维度来表示背包容量,但仍旧按照一维数组的思想来构造动态规划数组,所以需要背包容量从后往前遍历,即j--, i-- (因为两个维度都是背包)
int findMaxForm(vector<string>& strs, int m, int n) {vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0));//c++11遍历字符串for(string str: strs){int ZeroNum = 0, OneNum = 0;//统计01个数for(char str1:str){if(str1 == '0') ZeroNum++;else OneNum++;}for(int i = m; i>=ZeroNum ;i--){for(int j = n; j >=OneNum; j--){dp[i][j] = max(dp[i][j], dp[i - ZeroNum][j - OneNum] + 1);}}}return dp[m][n];