leetcode每日一题2021-6-8(01背包变式题)
链接:https://leetcode-cn.com/problems/last-stone-weight-ii/
1049. 最后一块石头的重量 II
思路:相当于将石头序列分为两堆重量最相近的石头,结果就是两堆石头的差值;这样就将问题转化为01选择问题,dfs时间复杂度为O(2^n): 2^30>1e9,所以采用01背包解决,O(NM),N=30,M=30100;
对于01背包,有两种使用方法:
方法1:一种是把f[j]看作容量为j的袋子可以最多装多少石头重量,状态转换方程是 f[j]=max(f[j],f[j-s[i]]+s[i]);f[j]也为f[j-1]的滚动数组。
这样的结果就是 ans-2f[ans/2],就是最相近的两堆重量差了,ans为总重量;
leetcode数组一定要初始化,vector则默认为0
代码:
int lastStoneWeightII(vector<int>& s) {
int f[3005];
memset(f,0,sizeof(f));
int ans=0;
for(int i=0;i<s.size();i++)ans+=s[i];
for(int i=0;i<s.size();i++){
for(int j=ans;j>=s[i];j--){
f[j]=max(f[j],f[j-s[i]]+s[i]);
}
}
int n=ans/2;
return ans-2*f[n];
}
方法2:第二种方法就是把f[j]看作石头堆能否堆出重量为j的石头堆,如果能f[j]=1,否则f[j]=0,状态转换方程为f[j]=f[j]||f[j-s[j]];边界是f[0]=1;其他全初始化为0;
class Solution {
public:
int lastStoneWeightII(vector<int>& s) {
int f[3005];
memset(f,0,sizeof(f));
f[0]=1;
int ans=0;
for(int i=0;i<s.size();i++)ans+=s[i];
for(int i=0;i<s.size();i++){
for(int j=ans;j>=s[i];j--){
f[j]=f[j]||f[j-s[i]];
}
}
for(int i=ans/2;i>=0;i--)
if(f[i])return ans-2*i;
return s[0];
}
};

浙公网安备 33010602011771号