翻硬币

来源:互联网 发布:上知教育老师培训多久 编辑:程序博客网 时间:2024/04/30 03:26

http://blog.chinaunix.net/space.php?uid=7390305&do=blog&id=2057295

有4枚硬币,初始状态未知。你的眼睛被蒙住,看不到硬币的状态,但可以随便翻任何几个硬币。你每翻一次以后,如果4枚硬币的状态是全正面朝上或者全背面朝上,旁边的人会告诉你翻成功了。现在问你,最少翻几次可以保证成功?每次翻哪几枚?百度2008年面试题

我 们用4位二进制数表示硬币的状态。由于最终的结果只要4枚硬币状态一样就行,正面还是背面没有关系,因此0000或1111都可以成功。由此又可以推出任 何两个互为反码的状态是等价的,比如1001和0110,对于我们的目标来讲没有区别。因此也不必关心0和1代表的是正面还是背面,只要知道他们的位置关 系就可以。

用X和O来表示翻硬币的方法。X表示把相应位置的硬币翻过来,O表示保持不动。同样的,互为补码的翻法是等价的,比如XXOO和OOXX对结果没有区别。

下面我们看看任一时刻,4枚硬币的状态一共有几种:

0001
0010
0100
1000
1100
1010
1001

除了成功状态以外,一共就只有这7种状态,其他的所有状态都和这7种中的某一种等价。同样的可以知道,翻法也只有7种。现在我们再取4枚硬币,把它们叫做演示硬币(相应的,原来的那4枚称作原始硬币),让演示硬币的初始状态为0000。我们每一次对原始硬币使用了什么翻法,就对演示硬币执行同样的操作。举个例子:如果原始硬币的初始状态为0010,第一次翻的时候用OOXO的翻法,那么翻过一次以后,原始硬币状态变成0000,演示硬币变成0010。

可以看到,在任一时刻,当且仅当演示硬币的状态和原始硬币的初始状态相同时,翻成功。而原始硬币一共有7种初始状态。因此,要保证成功,就必须使演示硬币能呈现出所有7种状态,这样才能保证原始硬币无论具有哪种初始状态都一定会在某一步成功。故最少需要7步。翻法如下:

步骤翻法翻过以后演示硬币的状态第1步OOOX0001第2步OOXX0010第3步OXXO0100第4步XXOO1000第5步OXOO1100第6步OXXO1010第7步OOXX1001

就是按照上面的步骤翻硬币,肯定能遍历所有的状态


第二问:现在将4枚硬币排成正方形(2*2的矩阵),每翻过一次以后,旁边有个人会将整个硬币图案旋转90度的任意倍数。有没有办法仍然保证能翻成功?最少需要几步?

面试官说20分钟内能解出这道题的人是天才。不过就我看来,找到解题的思路并不困难。

由于每一次都会随机的旋转,所以硬币的某个状态旋转成各种角度都是等价的,也就是说,下面每一行的状态都是等价的:

状态A0 1
0 0
1 0
0 0
0 0
0 1
0 0
1 0
状态B1 1
0 0
1 0
1 0
0 1
0 1
0 0
1 1
状态C0 1
1 0
1 0
0 1


可以看到,事实上只有3种不同的状态。同样的,由于在翻硬币之前会旋转,所以我们根本无法知道自己翻了哪一个硬币,只知道自己翻了几个,怎么排列。所以实际上只有3种翻法,和3种状态正好是类似的。

翻法xO X
O O
X O
O O
O O
O X
O O
X O
翻法yX X
O O
X O
X O
O X
O X
O O
X X
翻法zO X
X O
X O
O X


下面分析对每一种状态,执行每一种翻法之后会变成什么状态。结果单元格对应行是初始状态,列是翻法。用end表示成功(全0),“/”分隔几种可能的状态。


x  O X
   O O
y  X X
   O O
z  O X
   X O
A  0 1
   0 0
B/C/endAAB  1 1
   0 0
AC/endBC  0 1
   1 0
ABend

最后一行是突破的关键点,因为对C状态进行z翻法必定会结束,而其他的都不能保证结束。那么,我们的策略是想办法让A和B转换成C,然后用z就结束了。整个翻法如下:(列出每一种初始状态在进行到一定步数后的状态)

步骤翻法初始状态A初始状态B初始状态C第1步zABend第2步yAC/end
第3步zAend
第4步xB/C/end

第5步zB/end

第6步yC/end

第7步zend

最少7步保证结束。另外给出最少步数的证明:因为在不旋转的情况下都最少要7步,所以旋转情况下的步数不可能比7步少,否则的话就可以用旋转的解法来解决不旋转的问题,故最少需要7步。
原创粉丝点击