topcoder srm: NumbersChallenge

用bit mask来做枚举还挺方便的

这个大概是给你一个vector<int> array,求出这个array里任意几个元素加和所不能得到最小的整数。

元素个数最大20个,每个元素不超过100000

比如[1,2,4],那么就应该返回8. (因为3=1+1, 5=1+4等等)

所以枚举这个array的所有子集求和,之后从1开始查看哪个数没有命中然后返回就好。

tc上给出的题解如下:

static const int MAX = 100000 * 20 + 1; 
bool poss[MAX];
 
int MinNumber(vector<int> S)
{
    fill(poss, poss + MAX, false);
    int n = S.size();
    // All subsets:
    for (int mask = 0; mask < (1<<n); mask++) {
        int sum = 0;
        for (int i = 0; i < S.size(); i++) {
            if (mask & (1<<i)) {
                sum += S[i];
            }
        }
        poss[sum] = true;
    }
    int x = 1;
    while (poss[x]) {
        x++;
    }
    return x;
}

我自己又用dp小优化了下

static const int MAX = 100000 * 20 + 1;
     int MinNumber(vector<int> array) {
        int len = array.size();
        vector<int> buf(1<<len,0);
        bool res[MAX];
        fill(res,res+MAX,false);
        for(int mask = 1;mask<1<<len;mask++) {
            int tmp = mask;
            int maxBit = 0;
            while(tmp>>1) {
                maxBit++;
                tmp = tmp>>1;
            }
            buf[mask] = array[maxBit]+buf[mask&~(1<<maxBit)];
            res[buf[mask]] = true;
        }
        for(int i=1;i<MAX;i++) {
            if(res[i]==false) {
                
                return i;
            }
            
        }
        return MAX;
    }
原文地址:https://www.cnblogs.com/parapax/p/3768642.html