http://acm.hdu.edu.cn/showproblem.php?pid=4712

Hamming Distance

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others) Total Submission(s): 1610    Accepted Submission(s): 630

Problem Description
(From wikipedia) For binary strings a and b the Hamming distance is equal to the number of ones in a XOR b. For calculating Hamming distance between two strings a and b, they must have equal length. Now given N different binary strings, please calculate the minimum Hamming distance between every pair of strings.
 
Input
The first line of the input is an integer T, the number of test cases.(0<T<=20) Then T test case followed. The first line of each test case is an integer N (2<=N<=100000), the number of different binary strings. Then N lines followed, each of the next N line is a string consist of five characters. Each character is '0'-'9' or 'A'-'F', it represents the hexadecimal code of the binary string. For example, the hexadecimal code "12345" represents binary string "00010010001101000101".
 
Output
For each test case, output the minimum Hamming distance between every pair of strings.
 
Sample Input
2
2
12345
54321
4
12345
6789A
BCDEF
0137F
 
Sample Output
6
7
 
Source

分析:

输入n个数,用十六进制的方式输入的,任意选择其中的两个数进行异或,求异或后的数用二进制表示后1的个数最小的是多少?(n<=100000)

这题看了解题报告,大家都说用随机算法,试过了,随机100000次就过了,50000次都不行,但还是不懂这样怎么可以,唯一的解释就是这个值域也就是结果一共只有21个,

得出正确的结果的可能性很大,但是并不能100%保证结果是对的。无语第一次碰见这种算法。

首先,算汉明距离就是二进制异或以后的1的个数,统计1的个数用x&=x-1很快很神奇。

用if(x&1)  {count++;    x>>=1;}  在位数比较多的时候会慢一些。

然后就是看题解学到的神奇的“随机”!  来取到“任意的两个”  1w次wa,但是10w次就不会,20组testcase ,不会超时。

队友用随机函数在hduoj上交了五次(WA了4次)A了。也是醉啦 ,,,

AC代码:

 #include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;
int a[]; int main()
{
int tes,i,j,k,res,ans;
scanf("%d",&tes);
while(tes--)
{
int n;
scanf("%d",&n);
for(i=;i<n;i++)
scanf("%X",&a[i]); //16进制读取 res=; //结果初始为最大20
for(i=;i<=;i++)
{
j=rand()%n; //随机函数
k=rand()%n;
if(j==k)
continue;
ans=;
int tmp=a[j]^a[k]; //抑或
while(tmp) //抑或算1的个数,保存到ans中
{
if(tmp&)
ans++;
tmp>>=;
}
if(ans<res)
res=ans;
}
cout<<res<<endl;
}
return ;
}

网上贴的都是随机算法做的,下面找了一个非随机的思想。

题意:给你n个(n<=1e5)数a0~a(n-1)(ai<(1<<20))   要你求这n个数中转化为二进制后任意两个数中最小的汉明距离    \\  wiki百科:汉明距离

例如:a0 = 00000000010000000000   a1 = 00000000000000000001   a2 = 00000000000000000011

则答案为1 , 因为 a1^a2 = 00000000000000000010 其中1的个数为1,则答案为1

思路:

先说下随即算法的思路:首先当n比较小的时候,直接暴力枚举每两个数,求最小的汉明距离即可;当n比较大时,每次直接随即选出两个数a,b,求出汉明距离选取最小的即可。

因为ai<(1<<20),说明最终解一定<=20,解的范围很小,所以随即算法成功的几率还是很高的。

======================================================================================

首先要利用汉明距离的一个性质,二进制字符串的汉明距离也等于 n 维超正方体两个顶点之间的曼哈顿距离,其中n 是两个字串的长度。

我们先令(a,b)表示二进制字符a,b的汉明距离!!

怎么解释那个性质呢,就是比如有a,b,c三个二进制字符,其中(a,b)==(b,c)==1,那么(a,c) = (a,b)+(b,c) = 2

再加入一个d,假设(c,d)==1,且(d,a)!=1且(d,b)!=1,那么(d,a) = (a,b)+(b,c)+(c,d) = 3; (d,b) = (b,c)+(c,d) = 2;

(对于这个性质我一开始也是猜测,然后写了个小程序简单验证了一下,再后来仔细看汉明距离的wiki百科的时候才发现上面写着有。。。

怪不得题目上面一开始就表明了(From WIKI)。。。  )

有了这个性质接下来的事情就比较简单了

因为a<(1<<20),所以先把这(1<<20)个数当成(1<<20)个结点,然后把其汉明距离为1的结点连接起来,把边的长度设为1,

这样两个数的汉明距离即为这个图上两点间的最短路长度

如此一来,我们就可以把给出的n个数当成n个起点,然后在图上进行搜索,搜出任意两起点间最短的距离

搜索的方法就类似于多向BFS,具体的实现见代码

PS:多向BFS在搜索时,搜索到一个解并不能马上返回,需要把当前这一层的结点搜索完毕,然后返回一个最优值

比如下面这个图

可以尝试模拟一下,其中1,2,3表示搜索起点,当搜索到4号结点的时候,如果先行搜索红色边的话,则返回值是4,而正确解应该是3

AC代码:

 #include <iostream>
#include <cstring>
#include <stdio.h>
#include <math.h>
#include <fstream>
#include <algorithm>
#include <stack>
#include <vector>
#include <queue>
using namespace std; #define REP(i,n) for(int i=0;i<(n);i++)
#define FOR(i,j,k) for(int i=j;i<=(k);i++)
#define ll long long
#define base 20
#define maxn (1<<base)+10
/*
ifstream fin("1");
#define cin fin
*/
int a[],n; int Hash(char c){
if(c>=''&&c<='') return c-'';
return +c-'A';
}
void Input(int k){
char s[];
cin >> s;
int st = ;
REP(i,) {
st *= ;
st += Hash(s[i]);
}
a[k] = st;
} int dis[maxn],color[maxn];//dis表示距离,color相当于把从每个起点开始的搜索路径染色
queue <int> q;
int Solve(){
while(!q.empty()) q.pop();
memset(color,-,sizeof(color));
memset(dis,-,sizeof(dis));
REP(i,n){
if(dis[a[i]] != -) return ;
dis[a[i]] = ;
color[a[i]] = i;
q.push(a[i]);
}
int ans = 2e9,floor = 2e9; // ans 是答案 floor表示的是限定得到解的层数
while(!q.empty()){
int u = q.front(); q.pop();
REP(i,base){
int v = (u^(<<i));
if(dis[v] == -){
dis[v] = dis[u] + ;
color[v] = color[u];
// 只有当v的层数小于floor 才将其加入待搜队列
if(dis[v] <= floor) q.push(v);
}
else if(dis[v] != -){
if(color[v] == color[u]) continue; // 颜色相同则直接忽略
// return dis[v]+dis[u]+1; 直接返回是错误的!!!
ans = min(ans,dis[v]+dis[u]+);
floor = min(floor,dis[u]);
}
}
}
return ans;
} int main(){
int test;
cin >> test;
while(test --){
cin >> n;
memset(a,-,sizeof(a));
REP(i,n) Input(i);
cout << Solve() << endl;
}
}

hduoj 4712 Hamming Distance 2013 ACM/ICPC Asia Regional Online —— Warmup的更多相关文章

  1. hduoj 4710 Balls Rearrangement 2013 ACM/ICPC Asia Regional Online —— Warmup

    http://acm.hdu.edu.cn/showproblem.php?pid=4710 Balls Rearrangement Time Limit: 6000/3000 MS (Java/Ot ...

  2. hduoj 4706 Herding 2013 ACM/ICPC Asia Regional Online —— Warmup

    hduoj 4706 Children's Day 2013 ACM/ICPC Asia Regional Online —— Warmup Herding Time Limit: 2000/1000 ...

  3. hduoj 4707 Pet 2013 ACM/ICPC Asia Regional Online —— Warmup

    http://acm.hdu.edu.cn/showproblem.php?pid=4707 Pet Time Limit: 4000/2000 MS (Java/Others)    Memory ...

  4. hduoj 4708 Rotation Lock Puzzle 2013 ACM/ICPC Asia Regional Online —— Warmup

    http://acm.hdu.edu.cn/showproblem.php?pid=4708 Rotation Lock Puzzle Time Limit: 2000/1000 MS (Java/O ...

  5. hduoj 4715 Difference Between Primes 2013 ACM/ICPC Asia Regional Online —— Warmup

    http://acm.hdu.edu.cn/showproblem.php?pid=4715 Difference Between Primes Time Limit: 2000/1000 MS (J ...

  6. hduoj 4706 Children&#39;s Day 2013 ACM/ICPC Asia Regional Online —— Warmup

    http://acm.hdu.edu.cn/showproblem.php?pid=4706 Children's Day Time Limit: 2000/1000 MS (Java/Others) ...

  7. 2013 ACM/ICPC Asia Regional Online —— Warmup

    1003 Rotation Lock Puzzle 找出每一圈中的最大值即可 代码如下: #include<iostream> #include<stdio.h> #inclu ...

  8. HDU 4714 Tree2cycle(树状DP)(2013 ACM/ICPC Asia Regional Online ―― Warmup)

    Description A tree with N nodes and N-1 edges is given. To connect or disconnect one edge, we need 1 ...

  9. HDU 4749 Parade Show 2013 ACM/ICPC Asia Regional Nanjing Online

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4749 题目大意:给一个原序列N,再给出一个序列M,问从N中一共可以找出多少个长度为m的序列,序列中的数 ...

随机推荐

  1. backbone-todo案例分析

    todo案例可以到这个地址下载 https://github.com/jashkenas/backbone 添加数据后 todo案例不涉及Router,仅有Model.Collection.View的 ...

  2. go access database demo

    package main import ( "database/sql" "fmt" _ "github.com/lib/pq" " ...

  3. Python基本数据类型之int 、 float

    首先要明确的是:在python中,一切皆为对象. 从底层角度看,对象就是保存在内存中的一个数据块.从抽象层看,对象就是我们的代码模拟出的一个类的独立个体. 在python中变量不需要声明类型,也不需要 ...

  4. 【Android开发学习笔记】【第八课】五大布局-下

    概念 五大布局上一篇文章已经介绍了 LinearLayout RelativeLayout 这一篇我们介绍剩下的三种布局 FrameLayout 五种布局中最佳单的一种布局.在这个布局在整个界面被当成 ...

  5. 利用VS编译libiconv库

    参考文章:http://blog.csdn.net/ghevinn/article/details/9834119 关于中文字符编码问题,这篇文章里面讲的很详细-->http://www.tui ...

  6. jade复用

    jade复用说白了就是模板的继承. 使用 block 标识符,设置一个可修改的代码片段 layout.jade doctype html html head block title title Def ...

  7. 在sublime中使用less

    高亮显示: 可以在Less文件中显示语法高亮,这样看起来会更舒服一些. 按下Ctrl+Shift+P调出命令面板:输入install调出Install Package选项并回车:输入less,选中并安 ...

  8. Eclipse中直接双击执行bat时路径问题

    之前bat中使用的是 cd %cd% 这样在文件夹中直接运行bat是没问题的 但在eclipse中运行, 取得的路径就是eclipse.exe的所在路径 而如果需要获得bat文件的实际所在路径 应该使 ...

  9. Java学习-019-Properties 文件读取实例源代码

    在这几天的学习过程中,有开发的朋友告知我,每个编程语言基本都有相应的配置文件支持类,像 Python 编程语言中支持的 ini 文件及其对应的配置文件读取类 ConfigParse,通过这个类,用户可 ...

  10. centos linux

    centos 自带apache(httpd)不用安装 1.查看linux 版本号 方法1: cat /etc/redhat-release /etc/redhat-release配置文件用一行内容来声 ...