首页 > 代码库 > 格雷码

格雷码


B 连环锁 37% 7 19

总时间限制: 

1000ms
 
内存限制: 
65536kB
描述
许多人一定很熟悉九连环(如下图),九个环被串在一起,操作规则如下:第一个(右边)环可以任意装卸,如果第k个环没有被卸掉,而第k个环前边(右边)的所有环都被卸掉,则第k+1个环(第k个环左边的环)可以任意装卸(如果存在的话)。
用0表示此换被卸掉,1表示此环没有被卸掉,则九连环的每个状态可以用一个长度为9的二进制串来表示,如:111111001经过一次操作可以变成111111000,也可以变成111111011,111111111经过一次操作可以变成111111110,也可以变成111111101。

任务描述:
你现在要操作的是一个n连环,n为正整数,给出n连环的两种状态,计算出从第一种状态变换到第二种状态所需要的最少步数。
输入
第一行是一个正整数m,表示有m组测试数据。
每组测试数据一共3行,第一行是一个正整数n (0 < n < 128),后两行每一行描述一种状态,n个数(0或1),用空格隔开。
输出
对于每一组测试数据输出一行,一个非负整数,表示从第一种状态变换到第二种状态所需要的最少步数。
样例输入
230 0 01 0 041 0 0 00 1 1 0
样例输出
711

 

触到这个是因为 pkusc2013 

尝试的人很少  一开始觉得会是状态压缩dp类的 不过很明显不是。2^128种状态去吃翔吧,而且其实变换的方式也是固定套路,不存在方案的选择。因此理论上来说,递推是可行的,这种方式似乎比较像汉诺塔。

 

里我们说的是另外一种方法——格雷码

介绍是《九连环与格雷码不得不说的故事》【转】

分析解九连环的完全记法,由于每次只动一个环,故两步的表示也只有一个数字不同。下面以五个环为例分析。左边起第一列的五位数是5个环的状态,依次由第一环到第五环。第二列是把这个表示反转次序的五位数,似乎是二进制数,但是与第四列比较就可以看出这不是步数的二进制数表示。 

第三列是从初始状态到这个状态所用的步数。最右边一列才是步数的二进制表示。

  00000-00000-0-00000

  10000-00001-1-00001

  11000-00011-2-00010

  01000-00010-3-00011

  01100-00110-4-00100

  11100-00111-5-00101

  10100-00101-6-00110

  00100-00100-7-00111

  00110-01100-8-01000

  10110-01101-9-01001

  11110-01111-10-01010

  01110-01110-11-01011

  01010-01010-12-01100

  11010-01011-13-01101

  10010-01001-14-01110

  00010-01000-15-01111

  00011-11000-16-10000

  10011-11001-17-10001

  11011-11011-18-10010

  01011-11010-19-10011

  01111-11110-20-10100

  11111-11111-21-10101

  我们发现,右边一列数恰好是十进制数0到21的二进制数的格雷码! 这当然需要21步。如果把5位二进制数依次写完,就是

  10111-11101-22-10110

  00111-11100-23-10111

  00101-10100-24-11000

  10101-10101-25-11001

  11101-10111-26-11010

  01101-10110-27-11011

  01001-10010-28-11100

  11001-10011-29-11101

  10001-10001-30-11110

  00001-10000-31-11111

  这说明,对于只有5个环的五连环,从初始到状态11111用的不是并不是最多,到状态00001才是最多,用31步。类似,对于九连环,从初始到状态111111111用的不是并不是最多,到状态000000001才是最多,用511步。由于格雷码111111111表示二进制数101010101,表示十进制数341,故从初始状态到9个环全部上去用341步。这就是九连环中蕴涵的数学内涵。

  注 由二进制数转换为格雷码:从右到左检查,如果某一数字左边是0,该数字不变;如果是1,该数字改变(0变为1,1变为0)。例,二进制数11011的格雷码是10110.

  由格雷码表示变为二进制数:从右到左检查,如果某一数字的左边数字和是偶数,该数字不变;如果是奇数,该数字改变。

  例 格雷码11011表示为二进制数是10010.

  以上可以用口诀帮助记忆:2G一改零不改,G2奇变偶不变。

  例 设九连环的初始状态是110100110,要求终止状态是001001111,简单解法与完整解法各需要多少步?过程如何?

  解 初始状态110100110,格雷码是011001011,转换为二进制数是010001101,相应十进制数是141.终止状态是001001111,格雷码是111100100,转换为二进制数是101000111,相应十进制数是327.二者差326-141=186,完整解法需要186步。

 

其实,格雷码的转换不需要那么麻烦,这里给出一种简单的方式

异或转换

二进制码→格雷码(编码)
此方法从对应的n位二进制码字中直接得到n位格雷码码字,步骤如下:
  1. 对n位二进制的码字,从右到左,以0到n-1编号
  2. 如果二进制码字的第i位和i+1位相同,则对应的格雷码的第i位为0,否则为1(当i+1=n时,二进制码字的第n位被认为是0,即第n-1位不变)[5] 
公式表示
(G:格雷码,B:二进制码)
例如:二进制码0101,为4位数,所以其所转为之格雷码也必为4位数,因此可取转成之二进位码第五位为0,即0 b3 b2 b1 b0。
0 xor 0=0,所以g3=0
0 xor 1=1,所以g2=1
1 xor 0=1,所以g1=1
0 xor 1=1,所以g0=1
因此所转换为之格雷码为0111
格雷码二进制码(解码)
从左边第二位起,将每位与左边一位解码后的值异或,作为该位解码后的值(最左边一位依然不变)。依次异或,直到最低位。依次异或转换后的值(二进制数)就是格雷码转换后二进制码的值。
公式表示
(G:格雷码,B:二进制码)
原码:p[n:0];格雷码:c[n:0](n∈N);编码:c=G(p);解码:p=F(c);
书写时按从左向右标号依次减小,即MSB->LSB,编解码也按此顺序进行
举例:
如果采集器器采到了格雷码:1010
就要将它变为自然二进制:
0 与第四位 1 进行异或结果为 1
上面结果1与第三位0异或结果为 1
上面结果1与第二位1异或结果为 0
上面结果0与第一位0异或结果为 0
因此最终结果为:1100 这就是二进制码即十进制 12
当然人看时只需对照表1一下子就知道是12
...................c[n]=p[n],

练习的话  POJ1832、1090