416. 分割等和子集 416. 分割等和子集 - 力扣(LeetCode)
使用01背包解决
定义:物品种类=nums.size(),物品重量=i,背包大小=sum/2,判断能否刚好装满
递推公式:
初始化:dp(10001,0)
遍历顺序:正常顺序
1 2 3 4 5 for (int i=0 ;i<nums.size ();i++){ for (int j=sum/2 ;j>=nums[i];j--){ dp[j]=max (dp[j],dp[j-nums[i]]+nums[i]); } }
判断:即可
完整代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class Solution {public : bool canPartition (vector<int >& nums) { int sum = 0 ; for (int & i : nums) sum += i; if (sum % 2 != 0 ) return false ; int target = sum / 2 ; vector<int > dp (target + 1 , 0 ) ; for (int i = 0 ; i < nums.size (); i++) for (int j = target; j >= nums[i]; j--) dp[j] = max (dp[j], dp[j - nums[i]] + nums[i]); if (dp[target] == target) return true ; else return false ; } };
1049.最后一块石头的重量II 1049. 最后一块石头的重量 II - 力扣(LeetCode)
和上题思路一样,相当于划分集合,使得两集合相最小
直接给出答案
1 2 3 4 5 6 7 8 9 10 11 12 13 14 class Solution {public : int lastStoneWeightII (vector<int >& stones) { int sum = 0 ; for (int & i : stones) sum += i; int target = sum / 2 ; vector<int > dp (target + 1 , 0 ) ; 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]*2 ; } };
494.目标和 494. 目标和 - 力扣(LeetCode)
本题是装满有几种方法,是一个组合 问题,常用公式如下:
1 dp[j] += dp[j - nums[i]]
思路:还是分两个集合,两者相减为target
left+right=sum
left-right=target
left=(sum+target)/2
right=(sum-target)/2
定义:dp[j] 表示:填满j的包有dp[j]种方法
递推公式:已知nums[i],则凑成dp[j]就有dp[j - nums[i]] 种方法。
初始化:dp[0]=1
遍历顺序:先nums,后target
!注意的特殊情况,此时没有方案
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class Solution {public : int findTargetSumWays (vector<int >& nums, int target) { int sum = 0 ; for (int & i : nums) sum += i; if (abs (target) > sum) return 0 ; if ((sum + target) % 2 != 0 ) 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]; } };
474.一和零 474. 一和零 - 力扣(LeetCode)
特殊点:每个物品有两个维度的重量
定义::子集中i个0,j个1的最大长度
递推公式:计算str[i]中0、1个数记为m、n
初始化:
遍历顺序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class Solution {public : void func (string s, int & a, int & b) { a = b = 0 ; for (char i : s) { if (i == '0' ) a++; else b++; } } int findMaxForm (vector<string>& strs, int m, int n) { vector<vector<int >> dp (m + 1 , vector <int >(n + 1 , 0 )); int a=0 ,b=0 ; for (int k=0 ;k<strs.size ();k++){ func (strs[k],a,b); for (int i=m;i>=a;i--){ for (int j=n;j>=b;j--){ dp[i][j]=max (dp[i][j],dp[i-a][j-b]+1 ); } } } return dp[m][n]; } };