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代码:

  1. #include<iostream>
  2. #include<cstring>
  3. #include<string>
  4. #include<cmath>
  5. #include<cstdio>
  6. #include<algorithm>
  7. using namespace std;
  8. int a[];
  9.  
  10. int main()
  11. {
  12. int tes,i,j,k,res,ans;
  13. scanf("%d",&tes);
  14. while(tes--)
  15. {
  16. int n;
  17. scanf("%d",&n);
  18. for(i=;i<n;i++)
  19. scanf("%X",&a[i]); //16进制读取
  20.  
  21. res=; //结果初始为最大20
  22. for(i=;i<=;i++)
  23. {
  24. j=rand()%n; //随机函数
  25. k=rand()%n;
  26. if(j==k)
  27. continue;
  28. ans=;
  29. int tmp=a[j]^a[k]; //抑或
  30. while(tmp) //抑或算1的个数,保存到ans中
  31. {
  32. if(tmp&)
  33. ans++;
  34. tmp>>=;
  35. }
  36. if(ans<res)
  37. res=ans;
  38. }
  39. cout<<res<<endl;
  40. }
  41. return ;
  42. }

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

题意:给你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代码:

  1. #include <iostream>
  2. #include <cstring>
  3. #include <stdio.h>
  4. #include <math.h>
  5. #include <fstream>
  6. #include <algorithm>
  7. #include <stack>
  8. #include <vector>
  9. #include <queue>
  10. using namespace std;
  11.  
  12. #define REP(i,n) for(int i=0;i<(n);i++)
  13. #define FOR(i,j,k) for(int i=j;i<=(k);i++)
  14. #define ll long long
  15. #define base 20
  16. #define maxn (1<<base)+10
  17. /*
  18. ifstream fin("1");
  19. #define cin fin
  20. */
  21. int a[],n;
  22.  
  23. int Hash(char c){
  24. if(c>=''&&c<='') return c-'';
  25. return +c-'A';
  26. }
  27. void Input(int k){
  28. char s[];
  29. cin >> s;
  30. int st = ;
  31. REP(i,) {
  32. st *= ;
  33. st += Hash(s[i]);
  34. }
  35. a[k] = st;
  36. }
  37.  
  38. int dis[maxn],color[maxn];//dis表示距离,color相当于把从每个起点开始的搜索路径染色
  39. queue <int> q;
  40. int Solve(){
  41. while(!q.empty()) q.pop();
  42. memset(color,-,sizeof(color));
  43. memset(dis,-,sizeof(dis));
  44. REP(i,n){
  45. if(dis[a[i]] != -) return ;
  46. dis[a[i]] = ;
  47. color[a[i]] = i;
  48. q.push(a[i]);
  49. }
  50. int ans = 2e9,floor = 2e9; // ans 是答案 floor表示的是限定得到解的层数
  51. while(!q.empty()){
  52. int u = q.front(); q.pop();
  53. REP(i,base){
  54. int v = (u^(<<i));
  55. if(dis[v] == -){
  56. dis[v] = dis[u] + ;
  57. color[v] = color[u];
  58. // 只有当v的层数小于floor 才将其加入待搜队列
  59. if(dis[v] <= floor) q.push(v);
  60. }
  61. else if(dis[v] != -){
  62. if(color[v] == color[u]) continue; // 颜色相同则直接忽略
  63. // return dis[v]+dis[u]+1; 直接返回是错误的!!!
  64. ans = min(ans,dis[v]+dis[u]+);
  65. floor = min(floor,dis[u]);
  66. }
  67. }
  68. }
  69. return ans;
  70. }
  71.  
  72. int main(){
  73. int test;
  74. cin >> test;
  75. while(test --){
  76. cin >> n;
  77. memset(a,-,sizeof(a));
  78. REP(i,n) Input(i);
  79. cout << Solve() << endl;
  80. }
  81. }

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. X5学习笔记—给单元格添加颜色

    设置grid某一个单元格的颜色 可以用dhtmlxgrid的原生态方法 setCellTextStyle (row_id, ind, styleString) 参数: rowid:行id cellin ...

  2. [have_fun] 好玩哒小游戏又来啦

    联机贪吃蛇,相互厮杀,试一下吧! http://splix.io/

  3. javascript 原生事件综合查询

    click() 对象.click() 使对象被点击. closed 对象.closed 对象窗口是否已关闭true/false clearTimeout(对象) 清除已设置的setTimeout对象 ...

  4. c# ToString() 用法

    string tempa = Convert.ToString(31, 2);//将10进制数31转换为2进制字符串. string strNums = int.Parse(tempa).ToStri ...

  5. cdecl和stdcall调用约定-汇编演示

    . .model flat, stdcall .stack ExitProcess PROTO, dwExitCode:DWORD .data val2 sdword result dword ? . ...

  6. IE中的fireEvent和webkit中的dispatchEvent

    拿浏览器的click事件来说: 在IE浏览器中如果一个element没有注册click事件,那么直接调用的话会出现异常!当然如果你注册了没有什么可说的. 那么如果使用fireEvent来处理,clic ...

  7. To do

    小事{ android values public.xml 树.图的所有遍历方式和优劣 } 大事{ 通读android所有官网文档. android多dex多res开发框架. java AOT(and ...

  8. js实现表格中不同单元格内容的替换(不同浏览器的节点属性兼容问题)

      ------->   效果:点击右下角单元格,左下角单元格内容被替换成和左上角相同,如上图所示. 实现方式:分别获取各个节点,并将左边节点的内容修改成左上方节点的内容. 代码: 注意的地方: ...

  9. c#中栈和堆的理解

    之前对栈(stack)和堆(heap)的认识很模糊,今天看了一篇关于堆栈的文章<译文---C#堆VS栈>后,仿佛有种拨开云雾见青天的感觉,当然只是一些浅显的理论的认识,这里做一些简单的记录 ...

  10. 如何查看mac系统是32位还是64位的操作系统

    (一)点击工具栏左上角点击 (苹果Logo)标志,关于本机  -->  更多信息 --> 系统报告  -->(左侧栏中)软件 (二)打开终端,输入命令 uname -a 回车 x8 ...