zoj 2531 Traveller(暴力 || 二进制与gray码)

题目:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2531

Traveller Time Limit: 2 Seconds      Memory Limit: 65536 KB      Special Judge

A traveller plans a round trip through n cities, where n is a power of 2, in which case we simply indexthem with numeric values from 0 to n - 1. The traveller lives in one of them, and that's where hewill start and end his trip. He only visits each city once, and for some particular reason the twoadjacent cities on his trip should satify an equation that (A xor B) is also a power of 2.

For his odd mind no travel agency is willing to offer any help and finally he comes to you for a solution.You would either tell him it's not possible to arrange a trip for him.

Input

Input has two integers n and m, which are respectively the number of cities and the city he lives in.

Proceed through multiple cases until you meet a case n = 0.

Output

Print "NO" or a list of n city numbers on a single line separated by a single space.

Sample Input
2 1
4 0
0 0
Sample Output
1 0
0 1 3 2
分析:xor的意思是异或。在《C语言精选名题精选百则》中读过有关格雷码的问题,只是有个印象,没想到在这里居然又遇上了。开始只是用单纯的暴搜。。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;
const int maxn=1e6;
bool tag[maxn];
int que[maxn],q1,q2;
void dfs(int s){
    if(tag[s]) return ;
    tag[s]=1;
    que[q2++]=s;
    int length=log2(double(s));
    for(int i=0;i<=length;i++){
        int res=s^(1<<i);
        dfs(res);
    }
}
bool check(int n){
    bool ok=1;
    for(int i=0;i<n;i++)if(tag[i]==0) ok=0;
    return ok;
}
int main()
{
    //freopen("cin.txt","r",stdin);
    int n,m;
    while(cin>>n>>m&&n){
         int length=log2(double(n));
         for(int i=0;i<=length;i++){
             memset(tag,0,sizeof(tag));
             tag[m]=1;
             q1=q2=0;
             que[q2++]=m;
             int res=m^(1<<i);
             dfs(res);
             if(check(n)){
                 for(;q1<q2-1;q1++) printf("%d ",que[q1]);
                 printf("%d\n",que[q1]);
                 break;
             }
         }
    }
    return 0;

通过之后,我又查了查格雷码的相关知识:
在一组数的编码中,若任意两个相邻的代码只有一位二进制数不同,则称这种编码为格雷码(Gray Code)
在数字系统中只能识别0和1,各种数据要转换为二进制代码才能进行处理,格雷码是一种无权码,采用绝对编码方式,典型格雷码是一种具有反射特性和循环特性的单步自补码,它的循环、单步特性消除了随机取数时出现重大误差的可能,它的反射、自补特性使得求反非常方便。
下表为几种自然二进制码与格雷码的对照表:

十进制数

自然二进制数

格雷码

十进制数

自然二进制数

格雷码

0

0000

0000

8

1000

1100

1

0001

0001

9

1001

1101

2

0010

0011

10

1010

1111

3

0011

0010

11

1011

1110

4

0100

0110

12

1100

1010

5

0101

0111

13

1101

1011

6

0110

0101

14

1110

1001

7

0111

0100

15

1111

1000

自然二进制码转换成二进制格雷码
  自然二进制码转换成二进制格雷码,其法则是保留自然二进制码的最高位作为格雷码的最高位,而次高位格雷码为二进制码的高位与次高位相异或,而格雷码其余各位与次高位的求法相类似。
zoj 2531 Traveller(暴力 || 二进制与gray码)_第1张图片
二进制格雷码转换成自然二进制码
  二进制格雷码转换成自然二进制码,其法则是保留格雷码的最高位作为自然二进制码的最高位,而次高位自然二进制码为高位自然二进制码与次高位格雷码相异或,而自然二进制码的其余各位与次高位自然二进制码的求法相类似。

#include <iostream>
using namespace std;
int fac[100],top;
void turn(int x) {
        top=0;
	while(x){
	        fac[top++]=x%2;
		x/=2;
	}
	for(int i=top-1;i>=0;i--) cout<<fac[i];  cout<<endl;
}
int toGray ( int x )
{  return x ^ ( x >> 1 ); }
/*
int GraytoDecimal ( int x )
{
    int y = x;
    while ( x >>= 1 ) y ^= x;
    return y;
}
*/
int main()
{
    int n, m;
    while ( 1 )
    {
        cin >> n >> m;
        if ( n == 0 ) break;
        for ( int i = 0; i < n - 1; i++ )
        {
            cout << toGray ( (i+m) % n ) << ' '; //turn(DecimaltoGray ( (i+m) % n ));
        }
	cout << toGray ( (n-1+m) % n ) << ' ';  //turn(DecimaltoGray ( (n-1+m) % n ));
    }
    return 0;
}



你可能感兴趣的:(ZOJ,gray码)