一二三四五 上山打老虎

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-2
f[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];
    }
};
posted @ 2021-06-08 09:56  黒川川  阅读(79)  评论(0)    收藏  举报