Leetcode 474 - Ones and Zeroes(01背包)

来源:互联网 发布:中国技术贸易数据 编辑:程序博客网 时间:2024/06/09 15:13

题意

给定m个0个n个1,以及一堆字符串数组strs,要求你用这个m个0和n个1,去构成strs里面的字符串,求能够得到的最多字符串数目,可以剩余。

思路

就01背包,考虑第i个字符串是否选择。

状态表示d[i][j][k],去组成第i个字符串时,用了j个0,k个1能够得到的最多的字符串数目。
转移方程d[i][j][k]=max(d[i1][jZi][kOi]+1,d[i1][j][k]) 其中Zi代表第i个字符串中0的数目,Oi代表第i个字符串中1的数目。

细节

滚动数组优化空间
m和n可以剩余

代码

const int maxn = 1000 + 5;const int maxm = 100000 + 5;int d[2][maxn][maxn];int Z[maxm], O[maxm];class Solution {public:    int findMaxForm(vector<string>& strs, int m, int n) {        int nn = strs.size();        if (nn == 0) return 0;        memset(Z, 0, sizeof(Z));        memset(O, 0, sizeof(O));        memset(d, 0, sizeof(d));        for (int i = 0; i < strs.size(); i++) {            for (int j = 0; j < strs[i].length(); j++) {                if (strs[i][j] == '0') Z[i]++;                else O[i]++;            }        }        d[0][Z[0]][O[0]] += (Z[0] <= m && O[0] <= n ? 1 : 0);        int t = 0, res = d[0][Z[0]][O[0]];        for (int i = 1; i < nn; i++, t ^= 1) {            for (int j = 0; j <= m; j++) {                for (int k = 0; k <= n; k++) {                    d[t ^ 1][j][k] = d[t][j][k];                    if (j >= Z[i] && k >= O[i]) d[t ^ 1][j][k] = max(d[t][j - Z[i]][k - O[i]]  + 1, d[t][j][k]);                    res = max(res, d[t ^ 1][j][k]);                }            }        }        return res;    }};
0 0