1. 程式人生 > >2018百度之星資格賽___1001調查問卷——狀態壓縮

2018百度之星資格賽___1001調查問卷——狀態壓縮

補題連結:傳送門

題目大意:

  有TT組樣例,nn份問卷,每份問卷有mm個問題,答案由A或B組成(相當於nn條長度為mm的01序列),在這mm個問題中任意選取一部分,要使這新的零散問卷互不相同,且至少有k,問這樣選取一共有多少種方案???

解題思路:

  因為m<=10m<=10,所以一共只有2102^{10}種狀態,用狀態壓縮即可解決,還有一點就是kk種互不相同的狀態的儲存問題(當時因為這一點想了很久),看程式碼即可

程式碼思路:

  暴力列舉每種狀態即可,設A為0,只需要判斷是否為B即可

核心:考慮狀態的可行性和互不相同的判斷方法

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

char ch[1010][15];
int dp[1<<11], binary[1005];

int main()
{
	int cas=1, T;
	scanf("%d", &T);
	while(T--)
	{
		int n, m, k;
		scanf("%d%d%d", &n, &m, &k);
		getchar();
		for(int i=1; i<=n; i++) scanf("%s",ch[i]);
		if(n*(n-1)/2<k) 
		{
			printf("Case #%d: 0\n", cas++);
			continue;
		}
		
		int ans=0;
		for(int i=1; i<(1<<m); i++)
		{
			int num=0;
			memset(dp, 0, sizeof(dp));
			for(int j=1; j<=n; j++)
			{
				int tot=0;
				for(int t=0; t<m; t++) 
				{
					if(i&(1<<t) && ch[j][t]=='B')	
						tot += (1<<t);
				}
				
				binary[j] = tot;
				dp[tot] = 0;
			}
			
			for(int j=1; j<=n; j++) 
			{
				int k = ++dp[ binary[j] ];
				num += (j-k);
			}
			if(num>=k) ans++;
		}
		
		printf("Case #%d: %d\n", cas++, ans);
		
	}		
	return 0;
}