2018百度之星-1001调查问卷

这道题读起来可能有点费劲,大概就是现在有一份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++;
    }
}

猜你喜欢

转载自blog.csdn.net/King8611/article/details/81448216