码迷,mamicode.com
首页 > 其他好文 > 详细

Toad趣题:说真话的程序员 & 不说实话的经理

时间:2015-01-12 11:00:53      阅读:151      评论:0      收藏:0      [点我收藏+]

标签:算法   趣题   

FBI包围了诺恩公司的总部。里面总共有n个人。每个人不是工程师就是经理。机密文件已经被销毁,只有经理掌握。现在FBI要分辨他们。只能问i:“j是什么身份”。诺恩中每个人相互都知道身份。工程师只说真话;经理并不总是说真话,而且都足够狡猾,想尽方法迷惑FBI。(这个设定还是比较有意思的 :P)

1 假如一半以上的人都是工程师,是否有一个策略,用最多n-1次提问找到一个工程师。
2 假如有至少一半的人是经理,是否能找到一个工程师。

3 一旦找到了一个工程师,通过他可以认清其他人的身份。是否可以用更少的询问来达到目标。

4如果要确定所有人的身份,最少需要多少次询问


第一问,n-1次是一个限制比较苛刻的条件。不妨先把这个条件放松,不限制询问次数。注意到有一半以上的人说真话,那么问一遍所有人:第i个人是E(工程师)还是M(经理)。肯定有一半以上的人的答案是相同的,并且就是i的身份。通过这种方式,可以找出所有人的身份。

那么如何仅仅使用n-1次询问来达到目的呢?先放一放,看下面的。

第二问。让我们把问题特殊化:如果有2个人,一个是M,一个E。是否能找出各自的身份呢?答案是否定的。

首先注意到这样一个事实,如果询问i本人是什么身份,他如果是E,只会回答自己是E;他如果是M,可能回答的是E或M。但是M没有那么傻,如果他说自己是M,那么他一定是M;只有他说自己是E,我们才无法判断他的身份。所以询问某个人他自己的身份这样的问题是多余的。

在2个人的情况下,容易想到M的策略:是说对方是M。由于E说实话,他一定说对方是M。所以两个人都说对方是M,自己是E,我们没法判断谁是谁。

如果是任意偶数个人的情况,E和M是一半对一半。经理的策略总是说自己是工程师,对方人是经理;工程师说实话,也是这么说。我们可以知道哪些人是一个阵营,但却无法分辨出他们的阵营。

然后考虑有3个人的情况,E和M是1:2。这时候工程师1总是说其他人是M。经理2可以说其他人是M,经理3按照同样的策略。在外人看来,任何人都可以是E,其他人是M。所以我们无法判断。

如果有任意个人,策略可以有很多种:每个经理都可以说其他人是M,产生工程师只有一个的可能。这样我们就不知道工程师到底有几个。例如2:5的情况,经理3,4,5都说自己以外的所有人是M;工程师1、2说自己都是E,其他人是M。7个人中分成了4个阵营『1,2』『3』『4』『5』,相同阵营中的人身份是一致的,但是我们无法判断哪个阵营是E。

因此第二问的回答是否定的。


真正有复杂的是第一问。因为有次数限制。

人员按1到n。先把第一个人放到队列的开头。从第二个人开始,询问他队列最后一个人的身份。如果他回答是E,把他加到队列的最后;如果他的回答是M,把他和队列最后的一个人排除掉。通过n-1次询问,整个队列最开头的那个人一定是E。

注意到这样的事实:
1)如果整个过程当中有一半的人,或以上,说某个人是E,那么这个人确实就是E。
2)如果i说j是M,那么有可能出现  i是M,j是M;i是E,j是M;i是M,j是E。总之要么两个人都是M,要么有一个人M。如果把这两个排除,剩下的人的当中还是保持了有一半的人以上是E。
3)如果i认为j是E,那么i认可j所有的判断。如果有n个人,第2个人说第1个人是E,第3个人说第2个人是E……第n个人说n-1个人是E,那么所有人都认为第1个人是E。这就形成了一个“真话队列”。这个真话队列当中有一半以上的人是E,那么第一个人就是E
4)在以上的过程当中,我们就是维持这样一个真话队列,而且有一半以上的人是E。
因此上述算法是正确的



Toad趣题:说真话的程序员 & 不说实话的经理

标签:算法   趣题   

原文地址:http://blog.csdn.net/kingoverthecloud/article/details/42066915

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!