一道经典的黑白帽子问题

题目:黑白帽子问题

一百个犯人纵向站成一排,每人头上带上黑色或白色的帽子,各人不知道自己帽子的颜色,但是能看见自己前面所有人帽子的颜色。然后从最后边一个犯人开始,每人只能大声说一个字:“黑”或“白”,保证其他人都能听到(但声音中不会附加任何其他信息),如果说中了自己帽子的颜色就存活,说错了就拉出去枪决。在执行前,允许所有犯人可以聚在一起商量策略。那么如果犯人都足够聪明不会犯错,那么100个人最大的存活概率是多少?

分析

由于每个人看不到自己帽子的颜色,所以必需有自己后面的人给自己提供有用的信息才可以存活。好在每个人都可以看到自己前面所有人的帽子颜色,因此提供信息不难。但是尴尬的是,如果提供给前面的人信息,那么自己可能就活不了。同时,在报自己颜色的时候,又很难给别人提供信息。因此,问题的关键是如何在报自己帽子颜色的时候,又可以提供给前面的人以有用的信息,这样才可以保证尽可能多的人活下来。
注:为了讨论方便,所有的顺序都是从后向前,如“第1人”指的是整个一纵排的最后一人,他可以看到前面所有人的帽子颜色。

解法1:存活率 75%

最简单的办法,就是每奇数位人报前一人帽子的颜色,然后前一人再报自己的颜色,以此类推,直到排首。如,第1人能看到第2人的颜色,直接报出来告诉第2人,这样第2人在报的时候直接报出来就可以存活,但是第1个人因为报的是第2个人的帽子颜色,所以只有50%的几率正好与自己的颜色一样。在这种情况下,如果每对的颜色都是一样的,那么100人全部存活;反之,如果每对颜色都不一样,只有50人存活。
存活概率:50人肯定存活,另50人有一半的几率存活,所以存活率为 (100% × \times × 50 + 50% * 50 )/100 = 75%。

解法2:存活率 96.5%

由于后面的人能够看到所有人的帽子的颜色,所以我们可以利用这一点进行编码。我们很容易求出,100 的二进制码为 ‭1100100 需要7位即可‬,所以我们可以用最后面7个人进行编码对剩下93人的白帽子的数据进行表示。举例来说,比如在前93人中有52顶白帽子,其二进制编码为‭0110100,那么最后7个人可以用黑表示1,白表示0进行报颜色,即 [白,黑,黑,白,黑,白,白]。当前面所有93人听到这个组合时,根据之前商讨的约定,就会明白有52顶白帽子。这是倒数第8人开始报颜色了,虽然他看不见自己的颜色,但是可以看到前面92人的帽子颜色,由于已经知道了白色帽子的数量,所以只要统计一下前面92人帽子的颜色即可推算出自己帽子的颜色,比如数完白色帽子总数仍然是52,自己肯定是黑色的;反之如果白帽子变成51了,自己则也是白帽子。以此类推,直到最后一个人。(注:题目设定所有犯人“足够聪明不会犯错”这点非常关键)。
存活概率:此时93人肯定存活,7人50%概率,所以存活率为 (100% × \times × 93 + 50% * 7 )/100 = 96.5%。

解法3:存活率 99.5%

本解法利用奇偶性来解决,可以将白帽子的奇偶性作为关键点来考虑。具体算法如下:

  1. 让第1人先统计前99人的白帽子的个数,然后用黑表示奇数,白表示偶数告知前面所有99人。
  2. 下一人根据已经白帽子的奇偶性推算自己帽子的颜色,如果奇偶性改变了,则自己是白色,否则是黑色。
  3. 后面的人根据前人的颜色推断当前白帽子总数的奇偶性,回到2,直到所有人报完。

举例来说,假设总共有52帽白帽子,那么第1人会报白表示偶数。这样所有人都知道了有偶数顶的白帽子。第2人同样会统计前面98人的帽子,如果总数是奇数,白帽子总数的奇偶性由偶变奇了,所以自己也是白色,他报白即可。第3人听到第2人报白,会将当前白帽子总数的奇偶性变成奇数,然后继续进行报。
存活概率:此时99人肯定存活,1人50%概率,所以存活率为 (100% × \times × 99 + 50% * 1 )/100 = 99.5%。

总结

以上三种算法的结果差异很明显,尤其是最后一种,几乎保证了所有人都可以存活。差异产生的根据原因在于报颜色的时候,是否能够向前面的人提供有用的信息。第一种是每对间的信息完全是独立的,除了前一人的黑白信息对后一人有用外,对其他人完全无用,所以存活率最低。第二种,报颜色的同时还能够向后面所有人提供有用信息,所以保证了93人的存活,但是由于采用二进制的编码的方式,多占用了7人进行编码。第三种方案利用奇偶性只用了1个人就可以向所有人提供了所必需的信息,同时每个人在报的时候也向后面的人提供了有用信息,信息的利用率最高,所以让最多的人活了下来。第三种方案已经是最优解,无法再优化了,因为第1人是无论如何也不知道自己帽子颜色的,只有50%的概率存活,所以99.5%就是这个问题解的极限。

你可能感兴趣的:(算法设计与分析)