474. 一和零

思路:
第一次做01背包的题,但这类问题的状态转移方程的核心比较类似,都是 dp[i][j] = max(dp[i-1][j],dp[i-1][j-v[i]]+w[i]),这个状态转移方程可以去看专门的01背包解析获得更好的理解。那么对于01背包问题,更多的是如何转化成01背包的问题来求解,然后就直接上状态转移方程即可。
这道题要求在m个0以下,n个1以下的最大str子集,那么这里背包问题的背包容量上限就由m和n共同决定。因为子集每次获得数加1,那么该问题的状态转移方程为:dp[i][j][k]=max(dp[i-1][j][k],dp[i-1][j-zeros][k-ones]+1).
那么就算出strs数组里面每个元素的0和1的个数,然后三重for循环遍历i j k,赋值就判断当前的j是否大于当前0的个数并且k是否大于当前1的个数,如果满足说明有足够的容量装新的一个子集,那么就+1即可。否则就等于dp[i-1][j][k]
代码:

class Solution {
public:
    vector<int> getZeroOne(string& str){
        vector<int> zerosones(2);
        for(int i=0;i<str.length();++i){
            zerosones[str[i]-'0']++;
        }
        return zerosones;
    }
    int findMaxForm(vector<string>& strs, int m, int n) {
        int len = strs.size();
        vector<vector<vector<int>>> dp(len+1,vector<vector<int>>(m+1,vector<int>(n+1)));
        for(int i=1;i<=len;++i){
            vector<int> zerosones = getZeroOne(strs[i-1]);
            int zn = zerosones[0],on = zerosones[1];
            for(int j=0;j<=m;j++){
                for(int k=0;k<=n;k++){
                    dp[i][j][k] = dp[i-1][j][k];
                    if(j>=zn&&k>=on){
                        dp[i][j][k] = max(dp[i-1][j-zn][k-on]+1,dp[i][j][k]);
                    }
                }
            }
        }
        return dp[len][m][n];
    }
};
posted @ 2021-06-13 21:08  Mrsdwang  阅读(85)  评论(0编辑  收藏  举报