leetcode每日一题2021-6-6<一和零>(背包)
链接:https://leetcode-cn.com/problems/ones-and-zeroes/
思路:类似于经典01背包,选还是不选问题
经典01背包:
        const int M=10000;
        int f[M][M];
        memset(f,0xcf,sizseof(f));
        f[0][0]=0;
        for(int i=1;i<=n;i++){
            for(int j=0;j<=m;j++)
                f[i][j]=f[i-1][j];
            for(int j==ve[i];j<=m;j++)
                f[i][j]=max(f[i][j],f[i-1][j-ve[i]]+w[i]);
        }
        return f[n][m];
由于每一个阶段i状态都与上一个阶段的i-1状态有关(这里是直接相等了),用滚动数组优化掉一维,是空间复杂度降低,时间复杂度未变化
        const int M=10000;
        int f[M];
        memset(f,0xcf,sizseof(f));
        f[0][0]=0;
        for(int i=1;i<=n;i++){
            for(int j=m;j>=ve[i];j--)//由于正序时,f[j-ve[i]]已经修改,会计算重复,所以倒序
                f[j]=max(f[j],f[j-ve[i]]+w[i]);
        }
        return f[m];
代码:
            vector<pair<int,int>>ve;
            for(int i=0;i<strs.size();i++){
                int am=0,an=0;
                for(int j=0;j<strs[i].size();j++)
                    if(strs[i][j]=='0')am++;
                    else an++;
                ve.push_back({am,an});
            }
        int len=strs.size();
        int f[605][605];
        memset(f,0,sizeof(f));//注意初始化问题,如果不确定会到达边界,可以在最后遍历全部找最大的结果作为答案,
        for(int i=0;i<len;i++){
            int a=ve[i].first;
            int b=ve[i].second;
            for(int j=m;j>=a;j--)
                for(int k=n;k>=b;k--)
                f[j][k]=max(f[j][k],f[j-a][k-b]+1);
        }
        return f[m][n];

 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号