题意:有n个花瓶,每个花瓶都带有两种属性-形状和颜色,而每种属性都有36种不同的状态。求最大的k,使得k*k个花瓶的形状和颜色都有k种状态,且k*k个花瓶的两种属性都是由形状和颜色的k种状态组合而成的。
题解:我们用一个数组(comb[])存放形状和颜色,数组的下标为形状,然后将颜色状态压缩成为数组元素的值。这样一个数组元素就代表着,一个形状它对应了多少种颜色,而这个值也是这个形状对应的花瓶数。所以当与另一种形状的数组值,相与时,得到的结果如果大于等于2,那么也就代表着这两个形状至少有两种颜色是可以和他们任意匹配的,即找到了一个k=2,使得题目要求成立,而题目是求最大的k,所以我们记录当前算的k值为ans,两个数组值相与的值为cob,这样再与下一个形状的数组值相与,类似两个的计算,得到结果,更新ans即可。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAX_ = 40;
typedef long long LL;
int ans;
LL comb[MAX_];
int censor(LL cob){
int cnt = 0;
for(; cob; cob>>=1){
cnt += (cob&1);
}
return cnt;
}
void dfs(int k, int i, LL cob){
if(k >= ans)ans = k;
for(; i <= 36; i++){
if(censor(cob & comb[i]) >= k+1){
dfs(k+1,i+1,cob&comb[i]);
}
}
}
int main(){
int Case, n, s,d;
scanf("%d",&Case);
while(Case--){
scanf("%d",&n);
ans = 0;
memset(comb,0,sizeof(comb));
for(int i = 0; i < n; i++){
scanf("%d%d",&s,&d);
comb[s] |= (1LL << d);
}
dfs(0,1,(1LL<<36) -1);
printf("%d\n",ans);
}
return 0;
}