这道题读起来可能有点费劲,大概就是现在有一份m道题的调查问卷,然后让n个人做,现在要从这m道题中挑几道,使得剩下的题保证最少有k对人互相不一样。
应该算是比较简单,比较水的题吧。
我的思路就是用dfs枚举每一位,然后判断这一位是否合理。判断是否合理,可以用组合数学中的知识,复杂度为线性的:
从n个人中选两个,然后减去从每种情况下选两个的情况
枚举每一位情况的复杂度是2^m,判断的复杂度是n,整体就是n*2^m,差不多就是1e6的复杂度。
import java.util.*;
public class Main {
static int arr[]; //arr储存转化为二进制后,每种情况的个数
static int ans; //表示最终结果
static int num[]; //用来枚举每一位
static String str[];
static int k,n,m;
public static void main(String[] args){
arr=new int[1100];
num=new int[11];
Scanner sc=new Scanner(System.in);
int t=sc.nextInt();
for(int j=1;j<=t;j++){
ans=0;
n=sc.nextInt();
m=sc.nextInt();
k=sc.nextInt();
str=new String[n];
for(int i=0;i<n;i++)
str[i]=sc.next();
dfs(1);
System.out.println("Case #"+j+": "+ans);
}
}
static void dfs(int i){ //dfs枚举每一种情况,枚举后调用pan函数判断
if(i==m+1){
pan();
return;
}
num[i]=0;
dfs(i+1);
num[i]=1;
dfs(i+1);
}
static void pan(){
LinkedList<Integer> list=new LinkedList<Integer>(); //用一个队列把枚举过的情况储存起来,方便一会计算
for(int i=0;i<str.length;i++){
int sum=0,t=1;
for(int j=1;j<=m;j++){ //枚举二进制位
sum+=num[j]*t*(str[i].charAt(j-1)-'A');
t*=2;
}
arr[sum]++; //每出现一种情况,这种情况对应的arr+1
list.offer(sum);
}
int sum=n*(n-1)/2; //在n个数种选2个的情况
while(!list.isEmpty()){
int t=list.poll();
sum-=(arr[t]-1)*arr[t]/2; //减去相等的情况
arr[t]=0;
}
if(sum>=k)ans++;
}
}