USACO-Section2.1 Hamming Codes [搜索]

5 篇文章 0 订阅
3 篇文章 0 订阅

题目大意

给出 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。

格式

PROGRAM NAME: hamming
INPUT FORMAT:

(file hamming.in)
一行,包括 N, B, D。

OUTPUT FORMAT:

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

SAMPLE INPUT

16 7 3

SAMPLE OUTPUT

0 7 25 30 42 45 51 52 75 76
82 85 97 102 120 127

题解

在1到 2B 之间,递增的枚举开始的搜索点,然后用dfs()搜索第一次可以达到N个编码的集合。这题还是在练习位运算。可以用一个int来表示二进制编码,也可以用C++ STL的bitset。
下面给出两种实现:

代码1

不使用bitset
#include <iostream>
#include <fstream>
#include <cstring>
#include <bitset>
#define MAXN 70
#define MAXB 8 
#define cin fin
#define cout fout
using namespace std;
ifstream fin("hamming.in");
ofstream fout("hamming.out");

int N, B, D, MAX;
int rel[MAXN];

int count(int x) {
    int k = 1, cnt = 0;
    for (int i = 0; i < B; i++) {
        if (x & k) cnt++;
        k <<= 1;
    }
    return cnt;
}

bool dfs(int step) {
    if (step == N) {
        for (int i = 0; i < step-1; i++) {
            cout << rel[i];
            cout << (i % 10 == 9 ? "\n" : " ");
        }
        cout << rel[step-1] << endl;
        return true;
    }
    for (int i = 0; i < MAX; i++) {
        bool flag = true;
        for (int j = 0; j < step; j++) {
            if (count(i ^ rel[j]) < D) {
                flag = false;
                break;
            }
        }
        if (flag) {
            rel[step] = i;
            if (dfs(step+1)) return true;
        }
    }
    return false;
}

int main() {
    cin >> N >> B >> D;
    memset(rel, 0, sizeof(rel));
    MAX = 1 << B;
    for (int i = 0; i < MAX; i++) {
        rel[0] = i;
       if (dfs(1)) break;
    }
    return 0;
}

代码2

使用bitset
//#include<iostream>
#include<fstream>
#include<bitset>
using namespace std;
ifstream cin("hamming.in");
ofstream cout("hamming.out");
int a[65], N, B, D, ans=1;
int dfs(int n, int pre);
int main()
{
    cin >> N >> B >> D;
    for(int i=0; i<(1<<B); i++)
    {
        a[0] = i;
        if(dfs(N-1,0)) break;
    }
    cout << a[0] << " ";
    for(int i=1; i<ans-1; i++)
    {
        cout << a[i];
        if(!((i+1)%10)) cout << endl;
        else cout << " ";
    }
    cout << a[ans-1] << endl;
    return 0;
}
int dfs(int n, int pre)
{
    if(n==0) return 1;
    for(int i=a[pre]+1; i<(1<<B); i++)
    {
        bool ok = true;
        for(int j=0; j<ans; j++)
        {
            bitset<9> bit(i^a[j]);
            if(bit.count() < D)
            {
                ok = false;
                break;
            } 
        }
        if(ok)
        {
            a[ans] = i;
            if(dfs(n-1,++ans)) return 1;
        }
    }
    ans--;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值