UVa1326--Jurassic Remains(折半搜索)

题目大意:给出n个字符串,选择尽量多的串,使得各字母出现次数为偶数。


分析:见白书分析。另外,写一下自己对折半搜索的想法。首先,我们需要确定搜什么,然后对该对象进行折半,接着就是取与不取的问题了。


代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <map>
#include <algorithm>
using namespace std;

const int maxn = 30;

map<int, int> table;

char s[1000];
int n, A[maxn];

int bitcount(int x) { return x == 0 ? 0 : bitcount(x>>1)+(x&1); }

int main() {
    while(~scanf("%d", &n)) {
        for(int i = 0; i < n; i++) {
            scanf("%s", s);
            A[i] = 0;
            for(int j = 0; s[j] != '\0'; j++)
                A[i] ^= (1<<(s[j]-'A'));
        }
        table.clear();
        int n1 = n/2, n2 = n-n1;
        for(int i = 0; i < (1<<n1); i++) {
            int x = 0;
            for(int j = 0; j < n1; j++)
                if(i & (1<<j))    x ^= A[j];
            if(!table.count(x) || bitcount(table[x]) < bitcount(i)) table[x] = i;
        }
        int ans = 0;
        for(int i = 0; i < (1<<n2); i++) {
            int x = 0;
            for(int j = 0; j < n2; j++)
                if(i & (1<<j)) x ^= A[n1+j];
            if(table.count(x) && bitcount(ans) < bitcount(table[x])+bitcount(i)) ans = (i<<n1)^table[x];
        }
        printf("%d\n", bitcount(ans));
        for(int i = 0; i < n; i++)
            if(ans & (1<<i)) printf("%d ", i+1);
        printf("\n");
    }
    return 0;
}


你可能感兴趣的:(UVa1326--Jurassic Remains(折半搜索))