USACO2.1.5 Hamming Codes 海明碼 解題報告(列舉)
阿新 • • 發佈:2018-12-09
Description
給出 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。
Input
一行,包括 N, B, D。
Output
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
上面的輸出化為二進位制數如下
0000000 0000111 0011001 0011110 0101010 0101101 0110011 0110100 1001011 1001100 1010010 1010101 1100001 1100110 1111000 1111111
讓你找出N個數,這N個數最大為2^B,且每個數之間都至少有D位不同
從0-2^B列舉即可,將i和前面存下的所有答案對比,滿足條件就存進去,這裡我們判不同位的個數可以直接用異或(相同為0不同為1),然後用函式求出異或後'1'的個數即可
程式碼如下
#include <map> #include <queue> #include <cmath> #include <cstdio> #include <string> #include <cstring> #include <iostream> #include <algorithm> #define lowbit(a) (a&(-a)) #define _mid(a,b) ((a+b)/2) #define _mem(a,b) memset(a,0,(b+3)<<2) #define fori(a) for(int i=0;i<a;i++) #define forj(a) for(int j=0;j<a;j++) #define ifor(a) for(int i=1;i<=a;i++) #define jfor(a) for(int j=1;j<=a;j++) #define mem(a,b) memset(a,b,sizeof(a)) #define IN freopen("in.txt","r",stdin) #define OUT freopen("out.txt","w",stdout) #define IO do{\ ios::sync_with_stdio(false);\ cin.tie(0);\ cout.tie(0);}while(0) using namespace std; typedef long long ll; const int maxn = 150+10; const int INF = 0x3f3f3f3f; const int inf = 0x3f; const double EPS = 1e-7; const double Pi = acos(-1); const int MOD = 1e9+7; int Minbit; int a[maxn]; int cnt; bool juge(int x){ fori(cnt) if(__builtin_popcount(x^a[i])<Minbit) //編譯器內建函式,求出x^a[i]的二進位制數中'1'的個數 return false; return true; } int main(){ int n,b; cin >> n >>b >>Minbit; fori(1<<b){ if(juge(i)) a[cnt++] = i; if(cnt == n) break; } int cn = 1; fori(cnt){ cout <<a[i]; if(cn%10==0) cout << endl; else if(i!=cnt-1) cout <<" "; cn++; } return 0; }