USACO :Hamming Codes 解题报告

来源:互联网 发布:windows桌面图标 编辑:程序博客网 时间:2024/05/29 03:44

数据小,暴力搜索可以搞定。但是推荐使用DFS,每个节点(数)有取与不取两个分支。注意: 0是必须出现的。

证明如下:

最终得到的结果序列中,0是必须出现的,证明如下:
如果存在另一个满足要求的结果序列S={a1...an},其最小值为a1 = N > 0,
那么序列S' = S ^ N 是满足条件的最小解,且首元素为0

/*
ID: xpli1
PROG: hamming
LANG: C++
*/
#include <iostream>
#include <fstream>
#include <cstring> 
#include <cstdio>
#include <cmath>
using namespace std;

#define OUT cout
#define IN  cin

ofstream fout ("hamming.out");
ifstream fin ("hamming.in");

int N,B,D;
bool ham[256][256] = {false};
int res[65];
int dat[65];
int Max;
bool finded = false;

bool ham_dis(int a,int b){
 int mask = a^b;
 int dis = 0;
 for(int i=0; i<B; i++){
  dis += mask & 1;
  mask >>= 1;
 }

 return dis < D ? false : true;
}

void init(){
 int i,j;
 Max = 1<<B;
 for(i=0; i<Max-1; i++){
  for(j=i+1; j<Max; j++){
   ham[i][j] = ham_dis(i,j);
   ham[j][i] = ham[i][j];
  }
 }
}

void dfs(int k,int dep){
 if(finded) return;
 if(k == N) { 
  finded = true;
  memcpy(res,dat,65*sizeof(int));
  return;                              
 }                                      
 if(dep == Max) return;      
 
 int i;
 for(i=0; i<k; i++){
  if(!ham[dat[i]][dep]) break;
 }
 if(i==k){
  dat[k] = dep;
  dfs(k+1,dep+1);
  dat[k] = 0; 
 }

 dfs(k,dep+1); 
}

void output(){
 for(int i=0; i<N-1; i++){
  if(i%10 == 9)
   OUT << res[i] << endl;
  else OUT << res[i] << ' ';
 }
 OUT << res[N-1] << endl;
}

int main()
{
 IN >> N >> B >> D;

 init();
 
 dfs(0,0);

 output();

 return 0;
}

 

原创粉丝点击