USACO: 2.1.5 Hamming Codes 汉明码
一、题目描述
★Hamming Codes 汉明码
给出 N,B 和 D:找出 N 个编码(1 <= N <= 64),每个编码有 B 位(1 <= B <= 8),使得两两编码之间至少有 D 个单位的“汉明距离”(1 <= D <= 7).“汉明距离”是指对于两个编码,他们的二进制表示法中的不同二进制位的数目.看下面的两个编码 0x554 和 0x234 之间的区别(0x554表示一个十六进制数,每个位上分别是 5,5,4):0x554 = 0101 0101 0100
0x234 = 0010 0011 0100
不同的二进制位: xxx xx
因为有五个位不同,所以“海明距离”是 5.
PROGRAM NAME: hamming
INPUT FORMAT
一行,包括 N, B, D.
SAMPLE INPUT (file hamming.in)
16 7 3
OUTPUT FORMAT
N 个编码(用十进制表示),要排序,十个一行.如果有多解,你的程序要输出这样的解:假如把它化
为 2^B 进制的数,它的值要最小.
SAMPLE OUTPUT (file hamming.out)
0 7 25 30 42 45 51 52 75 76
82 85 97 102 120 127
二、解题思路
这个题目很简单,直接遍历就可以了。但是要弄清楚你需要什么,看清题意。首先我们应该明确0肯定在这N个编码中,有了遍历起点什么都好说了。
我们可以遍历1到最大的B位二进制数,依次比较当前数与已找到n个数之间是否满足D距离要求,直到找到N个编码。
当然在实现时会有一些细节不同,1.是否预处理找到所有B位数之间的距离;2.两数距离计算,可以通过直接异或再计算异或结果中1的个数,或逐位比较对应位是否相同。
源代码
#include<iostream>
#include<cstdio>
using namespace std;
int N,B,D;
int num[256+10];
int cout_num(int a){//计算B位数与0的距离,即B位数中1的个数
int i,cnt=0;
for (i=0;i<B;i++)
{ cnt=cnt+(a&1);
a=a>>1;
}
return cnt;
}
int isok(int x,int c,int d){
int i,temp;
for (i=0;i<c;i++)
{
temp=x^num[i];//异或结果,可以通过计算B位数x中1的个数
if (cout_num(temp)<d)
return 0;
}
return 1;
}
int main()
{
freopen("hamming.in","r",stdin);
freopen("hamming.out","w",stdout);
scanf("%d%d%d",&N,&B,&D);
num[0]=0; //0是必然会出现的。
int vis=0;
int i,j;
for (i=1;i<=256;i++)
{
if(isok (i,vis+1,D))
num[++vis]=i;
}
i=0;
for(i=0;i<N;i++){
printf("%d",num[i]);
if ((i+1)%10==0 || i==N-1)
cout<<endl;
else if (i<N-1)
printf(" ");//cout<<' ';不知怎么用cout输出空格
}
return 0;
}
由于自身是初学者,编程能力有限,未达到专业程序员的水平,可能误导大家,请大家甄读;文字编辑也一般,文中可能会有措辞不当。博文中的错误和不足敬请读者批评指正。