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];