hdu 6344 调查问卷

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
/*
1. 利用二进制枚举子集(问题的组合 <= 2 ^ m - 1),二进制的位为1,表示选择了它 
2. 对 1 的整数进行二进制解码,即得到选择了哪几个问题
3. 计算每一份调查问卷的hash值(A为1,B为0),利用mark[val]数组记录hash值为val的有多少个调查问卷
4. 计算有多少对问卷不同
   hash1->a1;hash2->a2;...hashk->ak;
   不同对数 = a1(a2+a3+...+ak) + a2(a3+a4+...+ak) + ... + ak-1(ak) 

*/
int mark[2000];
char str[1050][15];
int pow2[15];
vector<int> que;
int T;
int n,m,k;
int ans;
void deCode(int s) {
    int tmp = s;
    int index = 1;
    while (tmp != 0) {
        if (tmp % 2 == 1) {
            que.push_back(index);
        }
        index++;
        tmp = tmp / 2;
    }
    return;
}
int main() {
    scanf("%d",&T);
    int t = 1;
    //初始化2 ^ 1,2 ^ 2...... 
    memset(pow2,0,sizeof(pow2));
    pow2[0] = 1;
    for (int i = 1;i < 15;i++) {
        pow2[i] = pow2[i-1] * 2;
    }
    //
    while (t <= T) {
        scanf("%d%d%d",&n,&m,&k);
        for (int i = 0;i < n;i++) {
            scanf("%s",str[i]);
        }
        ans = 0;
        //枚举 
        
        int maxS = pow2[m] - 1;
        int hash = 0;
        for (int i = 1;i <= maxS;i++) {
            que.clear();
            deCode(i);
            memset(mark,0,sizeof(mark));
            //计算每个string的hash值 
            for (int p = 0;p < n;p++) {
                hash = 0;
                for (int q = 0;q < que.size();q++) {
                    if (str[p][que[q] - 1] == 'A') {
                        hash += pow2[que[q] - 1];
                    }
                }
                mark[hash]++;
                
            }
            //从后往前遍历,用sumSuffix记录aj+aj+1+...+ak; 
            int sum = 0;
            int sumSuffix = 0;
            for (int p = maxS;p >= 0;p--) {
                if (mark[p] != 0) {
                    sum += mark[p] * sumSuffix;
                    sumSuffix += mark[p];
                }
            }
            if (sum >= k) {
                ans++;
            }
        }
    
        printf("Case #%d: %d\n",t++,ans);
    }
    
    return 0;
} 

 

转载于:https://www.cnblogs.com/akira123/p/9542943.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值