USACO Hamming Codes DFS 构造

我还是用了很朴素的暴力匹配A了这题,不得不感叹USACO时间放的好宽...

/*

ID: wushuai2

PROG: hamming

LANG: C++

*/

//#pragma comment(linker, "/STACK:16777216") //for c++ Compiler

#include <stdio.h>

#include <iostream>

#include <fstream>

#include <cstring>

#include <cmath>

#include <stack>

#include <string>

#include <map>

#include <set>

#include <list>

#include <queue>

#include <vector>

#include <algorithm>

#define Max(a,b) (((a) > (b)) ? (a) : (b))

#define Min(a,b) (((a) < (b)) ? (a) : (b))

#define Abs(x) (((x) > 0) ? (x) : (-(x)))

#define MOD 1000000007

#define pi acos(-1.0)



using namespace std;



typedef long long           ll      ;

typedef unsigned long long  ull     ;

typedef unsigned int        uint    ;

typedef unsigned char       uchar   ;



template<class T> inline void checkmin(T &a,T b){if(a>b) a=b;}

template<class T> inline void checkmax(T &a,T b){if(a<b) a=b;}



const double eps = 1e-7      ;

const int M = 660000         ;

const ll P = 10000000097ll   ;

const int INF = 0x3f3f3f3f   ;

const int MAX_N = 20         ;

const int MAXSIZE = 101000000;



int n, b, d;

int ans[80];



bool func(int b){

    int i, j, cnt;

    int t1[50], t2[50];

    memset(t2, 0, sizeof(t2));

    while(b){

        t2[++t2[0]] = b % 2;

        b = (b - b % 2) / 2;

    }

    for(int k = 1; k <= ans[0]; ++k){

        cnt = 0;

        int a = ans[k];

        memset(t1, 0, sizeof(t1));

        while(a){

            t1[++t1[0]] = a % 2;

            a = (a - a % 2) / 2;

        }

        for(i = 1; i <= Max(t1[0], t2[0]); ++i){

            if(t1[i] != t2[i])  ++cnt;

        }

        if(cnt < d)    return false;

    }

    return true;

}



int main() {

    ofstream fout ("hamming.out");

    ifstream fin ("hamming.in");

    int i, j, k, t, n, s, c, w, q;

    fin >> n >> b >> d;

    ++ans[0];

    ans[1] = 0;

    int num = 1;

    while(ans[0] <= n){

        if(func(num)){

            ++ans[0];

            ans[ans[0]] = num;

        }

        ++num;

    }

    for(i = 1; i < ans[0]; ++i){

        fout << ans[i];

        if(i == ans[0] - 1){

            break;

        }

        if(i % 10 == 0) fout << endl;

        else    fout << ' ';

    }

    fout << endl;



    fin.close();

    fout.close();

    return 0;

}
View Code

不过看了官方题解觉得很不错,来分享一下

for (a = 0; a < maxval; a++)

        for (b = 0; b < maxval; b++) {

            dist[a][b] = 0;

            for (c = 0; c < B; c++) 

                if (((1 << c) & a) != ((1 << c) & b))

                    dist[a][b]++;

        }

通过以上这段代码可以找到所有1 << B 中所有数的关系,就是二进制下不同的位数

然后通过一个DFS 来找可行对

void findgroups(int cur, int start) {

    int a, b, canuse;

    char ch;

    if (cur == N) {

        for (a = 0; a < cur; a++) {

            if (a % 10)

                fprintf(out, " ");

            fprintf(out, "%d", nums[a]);

            if (a % 10 == 9 || a == cur-1)

                fprintf(out, "\n");

        }

        exit(0);

    }

    for (a = start; a < maxval; a++) {

        canuse = 1;

        for (b = 0; b < cur; b++)

            if (dist[nums[b]][a] < D) {

                canuse = 0;

                break;

            }

        if (canuse) {

            nums[cur] = a;

            findgroups(cur+1, a+1);

        }

    }

}

不难得出,核心代码很短也很好写

找到全部N个数之后输出一下就可以了

你可能感兴趣的:(USACO)