1. 程式人生 > >USACO-Section2.1 Hamming Codes [搜尋]

USACO-Section2.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。

格式

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;
}