动态规划
文章目录
- 一、最后一块石头的重量
- 二、目标和
- 三、一和零
- 总结
一、最后一块石头的重量
此题的关键在于转化思路,要求剩下最少的石块,也就是两堆相差不多的石块相互碰撞,所以求其中的一堆能够达到的最大数量,另外一堆也就随之确定,相减得到最少石块
转化后的问题和上一题相差无几
class Solution {
public:int lastStoneWeightII(vector<int>& stones) {//两对质量相差不多的石头堆int sum = 0; vector<int>dp(15001, 0);for (int i = 0; i < stones.size(); i++) sum += stones[i];int target = sum / 2;//一维数组,先遍历物品,在遍历背包for (int i = 0; i < stones.size(); i++) {for (int j = target; j >= stones[i]; j--) {dp[j] = max(dp[j], dp[j - stones[i]] + stones[i]);}}return sum - dp[target] - dp[target];}
};
二、目标和
此题的关键思路也是将问题转化,left - right = target, left + right = sum -------> left = (sum + target) / 2,问题可以转换为有多少种方法可以填满容量为left的背包
class Solution {
public:int findTargetSumWays(vector<int>& nums, int target) {//left - right = target, left + right = sum -------> left = (sum + target) / 2;//问题可以转换为有多少种方法可以填满容量为left的背包int sum = 0;for (auto i : nums) sum += i;if (abs(target) > sum) return 0;if ((sum + target) % 2 == 1) return 0;int bagsize = (sum + target) / 2;vector<int>dp(bagsize+1, 0);dp[0] = 1;for (int i = 0; i < nums.size(); i++) {for (int j = bagsize; j >= nums[i]; j--) {dp[j] += dp[j - nums[i]];}}return dp[bagsize];}
};
三、一和零
dp数组背包不同于之前的背包只有一个容量维度,这由m个0,n个1两个维度,需要二维数组
dp数组表示在m个1,n个0情况下,能够放下的最多的物品
class Solution {
public:int findMaxForm(vector<string>& strs, int m, int n) {//dp数组背包不同于之前的背包只有一个容量维度,这由m个0,n个1两个维度,需要二维数组vector<vector<int>>dp(m+1, vector<int>(n+1, 0)); //表示在m个1,n个0情况下,能够放下的最多的物品//重量相当于字符串中0,1的数量,价值相当于字符串的数量for (auto str : strs) {int x = 0;int y = 0;for (auto c : str) {if (c == '0') x++;else if (c == '1') y++;}for (int i = m; i >= x; i--) {for (int j = n; j >= y; j--) {dp[i][j] = max (dp[i][j], dp[i-x][j-y]+1);}}}return dp[m][n];}
};
总结
有点绕,需要由数学思维能力和问题转化能力
学习时间90min。
学习资料:《代码随想录》。