趣味算法:国王和100个囚犯

 

 在其它地方看到一道题目,估计有不少园友也已经看过了,也有同学解了,但本人比较愚,当时看到这个题目,我都快蒙了,还好有好心人给了些思路,于是,慢慢摸索着,用我们伟大的面向对象的思想来解这道题(虽然这道题跟面向对象没有半点关系)。

  题目如下:

  国王招来100个囚犯,对他们说:你们犯的是死罪,但我给你们一次求生的机会。15分钟以后,你们将被关进一个有100间隔离牢房的监狱里,每人一间牢房,都与外界隔绝,什么也听不见看不到,连时间都没法计算,无法获得外界的任何信息。

  这所监狱有一个院子,每天只少随机(注意是完全随机)打开一间牢房的门,让一个囚犯到院子里来放风。院子里有一盏灯,放风的囚犯可以控制它的开关,将它打开或是关闭。除囚犯之外,其他人都不会去碰开关。这盏灯会永远有充足的能源供应,灯泡和电路不会出故障。

  除了开关这盏灯,放风的囚犯放风时留下的任何其它痕迹都会在夜晚被清除干净(包括在灯上作的任何记号)。牢房是完全封闭的,院子里的灯光在牢房里看不到。只有放风到院子里的人才能看到。

  好了现在我向你们提出一个要求,只要你们做到了,就可以全部获得释放:

  给你们15分钟商量你们的方案。15分钟以后,你们将被关进我刚才说的那个监狱,永远无法再交流,被关若干天后,你们中间如果任何一个人能够向我证明你们每个人都至少放风了一次,我就把你们放了,不然永远别想再出来。

  好吧!这样吧,如果你们有谁现在可以告诉我这个方法,也就是能够证明你们每人至少放风一次的方法,我马上放掉你们!

  其中一个囚犯想了几分钟,回答了这个问题,国王听后,如自己所说的把他们全部给放了。请问那个囚犯是用什么方法证明的?

  大致的解题思路(建议思考后再看):

  代码

  囚犯们指定一人为计数人(A),A以外的囚犯每次出来放风时,如果看到灯是关闭的,则将灯打开,但如果已经开过一次灯,则不理会,当A出来放风时,如果灯是开着的,则将灯关掉,关一次则表示有一个人出来了一次,计数至100,完成。

  分析一下,这里面参与求解的东西无非就是监狱、灯、囚犯(计数员)。

  监狱:没有什么动作需要做的。

  灯:有一个状态标识, 提供开灯和关灯的方法。

  囚犯:有一个是否开过灯的标识,并带有一个开灯的方法

  计数员:继承囚犯,且拥有关灯的方法。

  实例代码:

  监狱:

  Prison

  1 /// <summary>

  2     /// 监狱

  3     /// </summary>

  4     public class Prison

  5     {

  6         /// <summary>

  7         /// 灯

  8         /// </summary>

  9         public Light Light { get; set; }

  10

  11         /// <summary>

  12         /// 牢房

  13         /// </summary>

  14         public Prisoner[] Prisoners { get; set; }

  15

  16         /// <summary>

  17         /// 随机数生成器

  18         /// </summary>

  19         Random random;

  20

  21         /// <summary>

  22         /// 囚犯数量

  23         /// </summary>

  24         private int PrisonerCount { get; set; }

  25

  26         /// <summary>

  27         /// 构造函数

  28         /// </summary>

  29         /// <param name="count">囚犯数量</param>

  30         public Prison(int count)

  31         {

  32             PrisonerCount = count;

  33             random = new Random(GetRandomSeed());

  34

  35             //初始化灯,并将状态设置为关

  36             Light = new Light() { Status = LightStatus.OFF };

  37

  38             //初始化牢房数组

  39             Prisoners = new Prisoner[PrisonerCount];

  40             for (int x = 0; x < PrisonerCount; x++)

  41             {

  42                 Prisoners[x] = new Prisoner() { NO = x };

  43             }

  44         }

  45

  46         public int Run()

  47         {

  48             SetCountPrisoner();

  49             bool finished = false;

  50             int count = 0;

  51             while (!finished)

  52             {

  53                 count++;

  54                 Helper.Print("{1}\t第 {0} 天", count, DateTime.Today.AddDays(count).ToString("yyyy-MM-dd"));

  55                 int x = GetRandomNumber();

  56                 var prisoner = Prisoners[x];

  57                 prisoner.Release();

  58                 prisoner.TrunLightOn(this.Light);

  59                 if (prisoner is CountPrisoner)

  60                 {

  61                     //ShowMsg("囚犯({0})是计数人", x);

  62                     var counter = prisoner as CountPrisoner;

  63                     counter.TrunLightOff(this.Light);

  64                     finished = counter.Finished;

  65                 }

  66             }

  67             return count;

  68         }

  69


本文转自 ☆★ 包罗万象网 ★☆ - http://www.baoluowanxiang.com 转载请注明出处,侵权必究!
原文链接:http://www.baoluowanxiang.com/a/program/csharp/2010/0810/1338.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值