UVALive - 3693 Balancing the Scale 枚举 + 状态压缩

题目大意:给出一个式子,和16个数字,问符合以下两个式子的情况有多少种
x1* 4 + x2* 3 + x3* 2 + x4 = x5 + x6* 2 + x7* 3 + x8* 4
y1* 4 + y2* 3 + y3* 2 + y4 = y5 + y6* 2 + y7* 3 + y8* 4

解题思路:枚举4个数字的全排列,然后找一下是否有其他4个数字的全排列的其中一种状况和当前这个情况相同,如果相同的话就加入.
要注意其他四个数字不能和当前这四个数字有交集
这样的话,就可以得到符合其中一个式子的情况的总数了(8位)
最后只需要统计一下cnt[i] * cnt[i ^ ((1 << 16) - 1)]的所有情况,再除以2,就是答案了

#include
#include
#include
#include
using namespace std;
const int N = (1 << 16);
const int M = 12000;
vector<int> sta[M];
int x[16], num[16], cnt[N];

void init() {

    for(int i = 1; i < 16; i++)
        scanf("%d", &num[i]);

    sort(num, num + 16);
    for(int i = 0; i < M; i++)
        sta[i].clear();
    memset(cnt, 0, sizeof(cnt));
}

bool judge(int s) {
    int count = 0;
    for(int i = 0; i < 16; i++)
        if(s & (1 << i)) 
            x[count++] =  num[i];

    return count == 4;
}


long long solve() {
    long long ans = 0;
    for(int i = 0; i < N; i++) 
        if(judge(i)) {
            do{
                int t = 4 * x[0] + 3 * x[1] + 2 * x[2] + x[3];
                for(int j = 0; j < sta[t].size(); j++) 
                    if((i & sta[t][j]) == 0)
                        cnt[i | sta[t][j]]++;
                sta[t].push_back(i);
            }while(next_permutation(x, x + 4));
        }
    for(int i = 0; i < N; i++)
        ans += cnt[i] *  cnt[i ^ (N - 1)];
    return ans / 2;
}

int main() {
    int cas = 1;
    while(scanf("%d", &num[0]) != EOF && num[0]) {
        init();
        printf("Case %d: %lld\n", cas++, solve());
    }
    return 0;
}

你可能感兴趣的:(ACM-高效算法设计)