1049. 最后一块石头的重量 II
知识点:动规
状态:看答案
思路:
跟分割等和子集一样,重量= 价值,分割等和子集就是找能不能找到一组 dp【sum/2】 = sum/2;有就true;
而本题也是找 dp【sum/2】 = sum/2;再最后对分成的两堆算差值
class Solution {
public:
int lastStoneWeightII(vector<int>& stones) {
int size = stones.size();
vector<int> dp(15001, 0); // 取重量为j的石头的最大价值
//dp[i][j] = max(dp[i-1][j], dp[i-1][j-weight[i] + val[i]])
int sum = 0;
for (int a : stones) sum += a;
int target = sum /2;
for(int i = 0; i < size; i++) {
for(int j = target ; stones[i] <= j ; j--) {
dp[j] = max(dp[j - stones[i]] + stones[i] , dp[j]);
}
}
return sum -dp[target] - dp[target];
}
};
494. 目标和
知识点:动规
状态:不会
思路:
最重要的是推到条件
注意测试用例有数组和的绝对值小于target觉得值的情况,此时无结果
class Solution {
public:
int findTargetSumWays(vector<int>& nums, int target) {
// l 为正数数组,r为负的数组
// l + r = sum
// l - r = target
// l = (sum + target)/2
int sum=0;
for(int a:nums) sum+=a;
if((sum + target)%2 == 1) return 0;
if( sum < abs(target) ) return 0;
int left = (sum + target)/2;
vector<int> dp(left + 1, 0);
// dp[j]为装满j的时候的组合数
dp[0] = 1;
for(int i = 0; i < nums.size();i++){
for(int j = left; nums[i] <= j; j--){
dp[j] += dp[j- nums[i]] ;
}
}
return dp[left];
}
};
474. 一和零
知识点:动规
状态:不会,看答案
思路:
本质上一样,只是重量条件变成了两个,同样都要是--
class Solution {
public:
int findMaxForm(vector<string>& strs, int m, int n) {
vector<vector<int >> dp(m+1 , vector<int> (n +1, 0)); // dp【i】【j】为有i个0和j个0的最大子集数
// dp[i][j] = max(dp[i-1][j], dp[i-1][j-weight[i] ] + val[i] )
// dp[j] = max(dp[j], dp[j-weight[i] ] + val[i] )
// dp[j] = max(dp[j], dp[j-weight[i] ] + val[i] )
// dp[i][j] = max(dp[i][j], dp[i-weight[i][j-weight[i] ] + 1)
for( string str : strs) {
int zeronum = 0;
int onenum = 0;
for(char a : str) {
if (a == '0') zeronum++;
else onenum++;
}
for(int i = m; zeronum <= i; i--) {
for(int j = n ; onenum <= j ; j-- ) {
dp[i][j] = max(dp[i][j], dp[i-zeronum][j- onenum ] + 1);
}
}
}
return dp[m][n];
}
};