USACO Hamming Codes

1、刚开始想到暴力法了,就是不太敢写,以后要敢于估计时间复杂度,看到可以写就果断暴力。

2、最后一个数据应该以\n结尾(虽然不能被10整除),WA一次,下次注意。

/*
ID:mrxy564
PROG:hamming
LANG:C++
*/
#include<cstdio>
using namespace std;
int N,B,D,cnt;
int a[100];
int dis(int a,int b){
    int c=a^b,ans=0;
 int bit=1;
 for(int i=0;i<B;i++){
     if(bit&c) ans++;
  bit<<=1;
 }
 return ans;
}
bool is_valid(int n){
    for(int i=0;i<cnt;i++){
     if(dis(n,a[i])<D) return false;
 }
 return true;
}
int main(){
 freopen("hamming.in","r",stdin);
 freopen("hamming.out","w",stdout);
 scanf("%d%d%d",&N,&B,&D);
 int num=(1<<B);
 cnt=0;
 a[cnt++]=0;
    for(int i=1;i<num;i++){
     if(is_valid(i))
   a[cnt++]=i;
  if(cnt==N) break;
 }
 for(int i=0;i<N;i++){
  if((i+1)%10!=0&&i!=N-1)
       printf("%d ",a[i]);
  else
    printf("%d\n",a[i]);
 }
 return 0;
}

官方题解:

There are only a few tools we need to solve this problem. First of all, we can use basic techniques to find the Nth bit of a number M: counting the least significant bit as bit 0, the next bit as bit 1, etc., we can find the value of that bit through the expression

          int Nth_bit = (1 << N) & M;

In other words, we are shifting the number 1 left by N spaces, and then performing a binary AND on the resulting number with our original number, which will leave either a 1 in the Nth bit or a 0. So the first thing we have to do is find out the distance between each pair of numbers within the set of all numbers with B bits (0..2B-1).

We also know that 0 can be one of the numbers in the set, because if the minimum number in the set were N instead of 0, we could XOR N to each number in the set and they would still be the same distance apart. The limits on the problem are low enough that we can do a DFS, and as soon as we hit a solution we can output it and exit.

#include <stdio.h>
#include <stdlib.h>
#include <iostream.h>
#define MAX (1 << 8 + 1)
#define NMAX 65
#define BMAX 10
#define DMAX 10

int nums[NMAX], dist[MAX][MAX];
int N, B, D, maxval;
FILE *in, *out;

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

int main() {
    in = fopen("hamming.in", "r");
    out = fopen("hamming.out", "w");
    int a, b, c;
    fscanf(in, "%d%d%d", &N, &B, &D);
    maxval = (1 << B);
    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]++;
        }
    nums[0] = 0;
    findgroups(1, 1);
    return 0;
}



 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值