USACO 2.1 海明码 Hamming Codes

题目

题目描述

给出 N,B 和 D,要求找出 N 个由0或1组成的编码(1 <= N <= 64),每个编码有 B 位(1 <= B <= 8),使得两两编码之间至少有 D 个单位的“Hamming距离”(1 <= D <= 7)。“Hamming距离”是指对于两个编码,他们二进制表示法中的不同二进制位的数目。看下面的两个编码 0x554 和 0x234(0x554和0x234分别表示两个十六进制数)

0x554 = 0101 0101 0100
0x234 = 0010 0011 0100
不同位    xxx  xx

因为有五个位不同,所以“Hamming距离”是 5。

输入输出格式

输入格式:

一行,包括 N, B, D。

输出格式:

N 个编码(用十进制表示),要排序,十个一行。如果有多解,你的程序要输出这样的解:假如把它化为2^B进制数,它的值要最小。

输入输出样例

输入样例#1: 复制
16 7 3
输出样例#1: 复制
0 7 25 30 42 45 51 52 75 76
82 85 97 102 120 127

说明

请解释:“必须与其他所有的数相比,Hamming距离都符合要求,这个数才正确”

答:如样例输出,0和7,0和25,0和……比较都符合海明码,同样7和25,7和30,7和……比较也符合要求,以此类推。 就这样了。 题中至少有D个单位,意思就是大于等于D个单位的都可以。

USACO 2.1

翻译来自NOCOW

 大意

     找到按字母序排前n个的数,满足其二进制位数相差大于等于D

    

分析

 这道题我们需要用到一点小技巧:

  a xor b 得到相同为0,不同为1的数

  解释一下k&(-k),结果就是去掉k右起第一个1的左边部分;

  对于一个带符号整型,-k的结果就是把k的符号位取反后的补码;

  举两个例子:当k=00010101时,-k=11101011;

     k=00010101

   -k=11101011

  k&(-k)=00000001

  当k=01001000时,-k=10110111;

     k=01001000

   -k=10111000

  k&(-k)=00001000

  也就是说k-=k&(-k)就可以做到,去掉k中最后一个1

  那么这个代码就很好理解了    //c。。

      然后暴力枚举就好了

代码

 1 #include<iostream>
 2 using namespace std;
 3 int n,b,d,k,num;
 4 bool ok;
 5 int a[100];
 6 int check(int x,int y)
 7 {
 8     int k=x xor y,ans=0;
 9     while (k>0)
10     {
11         ans++;
12         k-=k&(-k);
13     }
14     return ans;
15 }
16 int main ()
17 {
18     cin>>n>>b>>d;
19     while(k<n)
20     {
21         ok=1;
22         for (int i=1;i<=k;i++)
23            if (check(a[i],num)<d)
24            {
25                  ok=0;
26                  break;
27            }
28         if (ok==1) a[++k]=num;
29         num++;
30     }
31      while (k--){
32         cout<<a[n-k]<<" ";
33         if ((n-k)%10==0) cout<<endl;
34     }
35 }
为何要逼自己长大,去闯不该闯的荒唐
原文地址:https://www.cnblogs.com/zjzjzj/p/10289733.html