hduoj 4712 Hamming Distance 2013 ACM/ICPC Asia Regional Online —— Warmup
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
2
12345
54321
4
12345
6789A
BCDEF
0137F
7
分析:
输入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的更多相关文章
- 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 ...
- 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 ...
- 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 ...
- 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 ...
- 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 ...
- hduoj 4706 Children'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) ...
- 2013 ACM/ICPC Asia Regional Online —— Warmup
1003 Rotation Lock Puzzle 找出每一圈中的最大值即可 代码如下: #include<iostream> #include<stdio.h> #inclu ...
- 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 ...
- HDU 4749 Parade Show 2013 ACM/ICPC Asia Regional Nanjing Online
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4749 题目大意:给一个原序列N,再给出一个序列M,问从N中一共可以找出多少个长度为m的序列,序列中的数 ...
随机推荐
- 打造 PHP版本 1password
以前注册很多网站密码都使用简单密码,但是由于今年频繁曝出密码不安全问题,所以要使用更加复杂的密码.但是好多个账号,密码也不能设置成一样的,防止一个被盗全部不安全了,记密码就成了意见很头疼的事情. 在手 ...
- 查看linux库文件32位还是64位
查看linux库文件32位还是64位 分类: linux2014-09-25 09:46 238人阅读 评论(0) 收藏 举报 objdump -a *.a objdump -a *.so
- X Window 程式设计
X Window 程式设计 转 http://www.cppblog.com/zmj/archive/2007/05/18/24331.html X Window 程式设计 X Window 程式 ...
- 关于网站的UV分析
一:准备 1.统计的维度 guid tracktime provice 2.key与value的设定 key:date+provice_guid value:NullWritable 3.案例分析 表 ...
- Qt调用dll中的功能函数
声明: 事先我已经自己动手写了一个简单的dll文件(myDLL.dll),C版接口的.并且用我前两篇有关DLL文章里面的方法,从dll中导出了导入库(.lib)文件,dll中有两个函数,原型如下: ...
- zepto源码--几个判断函数--学习笔记
几个需要经常用到的类型判断: 自定义一个类似于typeof的函数,提供更多的类型判断. class2type[toString.call(obj)] 是对class2type的取值 在后面通过循环对c ...
- UITextView打开文字中的URL
1. 背景介绍 UITextView里显示的文字带有url,点击url可以打开对应的网页,可以分两种打开方式:(1)在App内打开url:(2)用safari打开url. 2. 实现代码: (1)声明 ...
- CS6破解
1) 序列号这里为大家生成了两个,可以通过软件验证:1325-0949-2080-9819-3777-32301325-0160-5283-9851-2671-8951 2) 破解补丁安装时会用到,请 ...
- Dictionary、SortedDictionary、Hashtable 、SortedList
HashTable数据结构存在问题:空间利用率偏低.受填充因子影响大.扩容时所有的数据需要重新进行散列计算.虽然Hash具有O(1)的数据 检索效率,但它空间开销却通常很大,是以空间换取时间.所以Ha ...
- 常用 linux 命令(部分)
常用命令总结: 1. mkdir命令 mkdir dirname , 用来创建目录.该命令创建由dirname命名的目录.如果在目录名的前面没有加任何路径名,则在当前目录下创建由dirname指定的目 ...