1. 程式人生 > >【HDU6344】調查問卷【狀壓】【模擬】

【HDU6344】調查問卷【狀壓】【模擬】

題目大意:

題目連結:http://acm.hdu.edu.cn/showproblem.php?pid=6344
給出 n n 個答卷,每個答卷有 m m 道判斷題,全部由 A

A B B 組成。這 m m 道判斷題裡有多少個題目子集,滿足至少有 k
k
對試卷在這些問題上面的答案是不同的。


思路:

m 10 m\leq 10 ,可以考慮先狀壓。
a

[ i ] a[i] 為第 i i 張試卷壓縮後的狀態,那麼列舉一個題目子集 S S ,將 S S 與所有試卷進行與運算,並記錄進一個 h h 陣列。如果現在列舉到第 j j 張試卷, h [ S & a [ j ] ] h[S\&a[j]] k k 個,那麼就有 j k j-k 張試卷可以和第 j j 張試卷匹配。最終判斷匹配數,如果超過要求,這個子集就是可以的, a n s ans 加一。


程式碼:

#include <cstdio>
#include <iostream>
#include <cstring>
#define N 1010 
#define MAXN 1023
using namespace std;

int t,n,m,k,sum,ans,a[N],h[MAXN+10];
char c;

int main()
{
	scanf("%d",&t);
	for (int l=1;l<=t;l++)
	{
		scanf("%d%d%d",&n,&m,&k);
		memset(a,0,sizeof(a));
		for (int i=1;i<=n;i++)
		 for (int j=m-1;j>=0;j--)
		 {
		 	cin>>c;
		 	if (c=='A') a[i]+=(1<<j);  //狀壓
		 }
		ans=0;
		for (int i=1;i<(1<<m);i++)
		{
			sum=0;
			memset(h,0,sizeof(h));
			for (int j=1;j<=n;j++)
			{
				h[i&a[j]]++;  //記錄個數
				sum=sum+(j-h[i&a[j]]);
			}
			if (sum>=k) ans++;
		} 
		printf("Case #%d: %d\n",l,ans);
	}
}