3231. 【佛山市选2013】海明距离

Description

对于二进制串a,b,他们之间的海明距离是指两个串异或之后串中1的个数。异或的规则为:

0 XOR 0 = 0

1 XOR 0 = 1

0 XOR 1 = 1

1 XOR 1 = 0

计算两个串之间的海明距离的时候,他们的长度必须相同。现在我们给出N个不同的二进制串,请计算出这些串两两之间的最短海明距离。

Input

第一个数字是整数T(T≤10),代表数据的组数。

接下来有T组数据,每组数据的第一行是一个正整数N,代表不同的二进制串的个数。接下来是N行,每行都是一个二进制串(长度是5)。我们用数字(0-9)和字符(A-F)来表示这个二进制串。它代表这个二进制串的16进制码。例如,“12345”代表的二进制串为“00010010001101000101”。 

Output

对于每个数据,请输出一个整数,即答案值。

Sample Input

2

2

12345

54321

4

12345

6789A

BCDEF

0137F

Sample Output

6

7

Data Constraint

对于30%的数据有1≤N≤100

对于全部数据,有1≤N≤100000

Solution

一开始打了个正确性显然为0的贪心trie。

后来才发现正解是搜索。。。

对于每个点加入进trie里面,然后dfs两个子树,加个最小值ans的剪枝就过了。

时间复杂度O(Tn*2^20)。

注意过程比函数要快。

Code

#include<cstdio> 
#include<cstring>
#include<algorithm>
#include<cmath>
#define I int
#define ll long long
#define F(i,a,b) for(I i=a;i<=b;i++)
#define Fd(i,a,b) for(I i=a;i>=b;i--)
#define N 100005
using namespace std;
I T,n,p[30],ans,s,x,y,tot,cnt,now,tr[N*20][2];
char c;
void R(I &x){
	x=0;c=getchar();
	while(c<'0'||c>'9') c=getchar();
	while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
}
void dg(I x,I k,I y,I z){
	if(z>=ans) return;
	if(k>19){
		ans=min(ans,z);
		return;	
	}
	if(tr[x][0]) dg(tr[x][0],k+1,y,z+((y>>k)&1));
	if(tr[x][1]) dg(tr[x][1],k+1,y,z+1-((y>>k)&1));
}
void ins(I x){
	now=1;
	F(i,0,19){
		y=(x>>i)&1;
		if(!tr[now][y]) tr[now][y]=++tot;
		now=tr[now][y];
	}
}
I main(){
	freopen("distance.in","r",stdin);
	freopen("distance.out","w",stdout);
	p[0]=1;
	F(i,1,23) p[i]=p[i-1]*2;
	R(T);
	while(T--){
		R(n);ans=24;
		memset(tr,cnt=0,sizeof tr);
		tot=1;
		while(n--){
			s=0;cnt++;
			F(i,1,5){
				c=getchar();x=0;
				while((c<'0'||c>'9')&&(c<'A'||c>'F')) c=getchar();
				if(c>='0'&&c<='9') x=c-'0';
				else x=c-'A'+10;
				F(j,0,3) if((x>>j)&1) s+=p[i*4-j-1];
			}
			dg(1,0,s,0);
			ins(s);
		}
		printf("%d\n",ans);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/zsjzliziyang/article/details/107870794