CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
可用分押宝游戏火热进行中... 专题改版:Java Web 专题
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  C/C++ >  非技术区

看到一个有趣的问题,我把它改成了编程题,有兴趣的新手可以做一做。4个以上三角的人做了不给分。

楼主A_B_C_ABC(黄瓜@YouCanDoIt)2006-04-05 22:52:30 在 C/C++ / 非技术区 提问

 
   
  国王招来100个囚犯,对他们说:你们犯的是死罪,本应该将你们统统杀掉,但我慈悲为怀,  
  给你们一次求生的机会。15分钟以后,你们将被关进一个有100间隔离牢房的监狱里,每人  
  一间牢房,都与外界隔绝,什么也听不见、看不到,连时间都没法计算,更别说获得外界的  
  任何信息。(送饭除外,但也是不规律的送)  
   
  这所监狱有一个院子,每天会随机打开一间牢房的门,让那个囚犯到院子里来放风。院子里  
  有一盏路灯,放风的囚犯可以控制它的开关,将它打开或是关闭。除囚犯之外,  
  其他人都不会去碰开关。这盏灯会永远有充足的能源供应,如果灯泡坏了或是电路出了故障会马  
  上修好,当然修理人员不会改变灯的状态(开或关)。  
   
  除了开关这盏灯,放风的囚犯放风时留下的任何其它痕迹都会在夜晚被清除干净(包括在灯上作的  
  任何记号)。  
   
  牢房是完全封闭的,院子里的灯光在牢房里看不到。只有放风出到院子里的人才能看到。  
   
  好了现在我向你们提出一个要求,只要你们做到了,就可以全部获得释放:  
   
  若干天以后,你们中只要有任何一个人能够向我证明所有的人都曾到院子里去过,你们就全体  
  释放。当然要有证据!因为我只会给你们一次机会,如果向我证明的那个人无法自圆其说,你们  
  就全部砍头。所以,要珍惜这次机会。如果你们永远做不到我的要求,你们就全部关到死.  
   
  现在给你们15分钟商量你们的方案。15分钟以后,你们将被关进我刚才说的那个监狱,永远无法再交流。  
   
     
  ==================================  
  灯的初始状态是开还是关,犯人们不知道。  
  请帮助这100个囚犯出监狱。  
   
  编程输出:  
  灯的初始状态:?(随机的)  
  向国王证明100人都已放过风的囚犯编号:?(由编程者指定)  
  出监狱时已经过了多少天:?(随机的)  
   
  其中  
  囚犯1号放风:?次(随机的)  
  囚犯2号放风:?次(随机的)  
  囚犯3号放风:?次(随机的)  
  ......  
  囚犯100号放风:?次(随机的)  
  问题点数:99、回复次数:103Top

1 楼ykzhujiang(朱朱)回复于 2006-04-05 22:58:24 得分 0

先mark一下Top

2 楼cunsh(村少)回复于 2006-04-05 23:00:58 得分 0

markTop

3 楼du51(郁郁思扬)回复于 2006-04-06 00:00:02 得分 9

//我没有三角  
  #include<iostream>  
  using   namespace   std;  
  void   make()  
  {  
          srand(time(0));  
          int   init=rand()%2,temp,prisoner[100]={0},day=1,times[100]={0},i;  
          cout<<"第1号囚犯报告的"<<endl;  
          if(init)cout<<"初始状态为亮"<<endl;  
          else   cout<<"初始状态为暗"<<endl;  
          init=0;prisoner[0]=1;  
          times[0]=1;  
          while(prisoner[0]<100)  
          {  
                  day++;  
                  temp=rand()%100;  
                  times[temp]++;  
                  if(temp)  
                  {  
                          if(!init&&!prisoner[temp])  
                          {  
                                  init=1;  
                                  prisoner[temp]=1;  
                          }          
                  }  
                  else    
                  {  
                          if(init)  
                          {  
                                  init=0;  
                                  prisoner[0]++;  
                          }  
                  }  
          }    
          for(i=0;i<100;i++)  
          {  
                  cout<<"第"<<i+1<<"号囚犯出来了"<<times[i]<<"次"<<endl;  
          }  
          cout<<"总共用了"<<day<<"天"<<endl;  
          cout<<"竟然用了"<<day/365<<"年还要多"<<endl;  
  }    
  int   main()  
  {  
          make();  
          system("PAUSE");  
          return   0;  
  }          
                   
  Top

4 楼cattlenzq(吃狼的豆腐(不要给分了,散起来真麻烦!))回复于 2006-04-06 00:41:31 得分 0

不明白怎么才能证明所有人都去过院子。。。。。。。。。Top

5 楼A_B_C_ABC(黄瓜@YouCanDoIt)回复于 2006-04-06 01:28:34 得分 0

du51(郁郁思扬)   够快,不过仍有小bug.  
  先是init=rand()%2;  
  但在循环前又init=0;这等于是给囚犯们说,一开始灯的关着的,与实际不附。Top

6 楼du51(郁郁思扬)回复于 2006-04-06 01:36:21 得分 0

先是init=rand()%2;  
  这是初始的状态...0表示暗,1表示亮.(随机的)  
  init=0更简单了.我指定的囚犯,无论明暗把它关掉就是了.  
      init=0;prisoner[0]=1;  
          times[0]=1;  
  这三句..就是我指定第一个囚犯..  
  她无论明暗关掉.然后,她关灯的次数置为1  
   
   
  Top

7 楼A_B_C_ABC(黄瓜@YouCanDoIt)回复于 2006-04-06 01:47:54 得分 0

du51(郁郁思扬)的第二个bug是   预设prisoner[0]=1;,那么当  
      一开始灯是开着的,且第一次就是报告人出来,关了灯,计数加1等于2,就是说以后当98个囚犯出来过,还有一个没出来时,他就急于报告国王说全部都出来过了,结果就把囚犯们害死了。  
   
  虽然说99个囚犯出来都100次上下了,而有一个没出来过,这种概率非常小,但国王要的不仅是实际是否全部人都出来过,而且要报告人能自圆其说。  
  Top

8 楼A_B_C_ABC(黄瓜@YouCanDoIt)回复于 2006-04-06 01:51:43 得分 0

du51(郁郁思扬)   ,想不到这么晚你还在啊Top

9 楼wumingchenchao(一缕阳光)回复于 2006-04-06 11:35:18 得分 0

markTop

10 楼jinjiajie(leorio)回复于 2006-04-06 12:46:52 得分 0

想不通...有解释下思路的吗?感觉没有合适的方法呢...因为可能性太多了,完全有可能几百年都放不出来涅Top

11 楼adintr(www.adintr.com)(风流总被雨打风吹去)回复于 2006-04-06 12:51:48 得分 0

markTop

12 楼acbbli(扎啤)回复于 2006-04-06 13:03:21 得分 0

国王肯定要让100个人都出去放风的,不然谁也无法证明啊。  
    而君无戏言么,有这点就可以证明了。Top

13 楼hehe(呵呵)回复于 2006-04-06 13:56:50 得分 0

markTop

14 楼adintr(www.adintr.com)(风流总被雨打风吹去)回复于 2006-04-06 14:29:41 得分 0

似乎没有什么方法能证明Top

15 楼tykmn(C&J)回复于 2006-04-06 14:46:11 得分 10

想到一个办法可以证明了,大家看看有没有问题;  
  100个囚犯商量制定这样的策略:  
  1、第一天出去的犯人,不管灯是什么状态都把它关掉。  
  2、选出一个人,专业负责以后的关灯,对这个人的唯一要求是记性较好。不妨假设是100号。  
    而其他人的要求是能记住自己是否开过灯,如果这点也做不到就死定了。  
  3、从第二天开始。除被选上的那个100号外每个放出去的人,如果他曾经开过灯了,那么他不做任何动作,否则观察灯的状态,如果是关着的,就把它开了,如果开着,他也不要做任何动作。  
  如果是100号被放出去放风了,那么他看到灯亮的话就关掉,如果是关着的,就不要去碰。而且一定一定要记住自己关过多少次灯。  
  当他第九十九次关掉灯的时候,就可以去找国王放人了。  
  其他问题用编程方法不难,就不写了。  
  用这种方法最好的情况是201天可以得到释放,最坏嘛,……呵呵……  
  平均的话,大概要201*100=大约55年多。求上天保佑了…………Top

16 楼tykmn(C&J)回复于 2006-04-06 14:49:41 得分 0

想到一个办法可以证明了,大家看看有没有问题;  
  100个囚犯商量制定这样的策略:  
  1、第一天出去的犯人,不管灯是什么状态都把它关掉。  
  2、选出一个人,专门负责以后的关灯,对这个人的唯一要求是记性较好,不妨假设选上的是100号。   而其他人的要求是能记住自己是否开过灯,如果这点也做不到就死定了。  
  3、从第二天开始。除被选上的那个100号外每个放出去的人,如果他曾经开过灯了,那么他不做任何动作,否则观察灯的状态,如果是关着的,就把它开了,如果开着,他也不要做任何动作。  
  4、如果是100号被放出去放风了,那么他看到灯亮的话就关掉,如果是关着的,就不要去碰。而且一定一定要记住自己关过多少次灯。  
  5、当100号他第九十九次关掉灯的时候,就可以去找国王放人了。  
  其他问题用编程方法不难,就不写了。  
  用这种方法最好的情况是201天可以得到释放,最坏嘛,……呵呵……  
  平均的话,大概要201*100=大约55年多。求上天保佑了…………  
  不知还有没有更好的办法Top

17 楼kkbspod(我被可乐淹死了)回复于 2006-04-06 14:53:56 得分 10

不管起始如何,让第一个出去的人(也就是第一天出去的人)把电灯置于开的状态。  
  并且让第一个人向国王证明。  
  以后所有的人只要看到电灯时开着的就把电灯熄灭,熄灭过一次的人第二次不再熄灭电灯。  
  以后再选到第一个人出去时,如果电灯熄灭,打开电灯,心里计数加1;如果电灯开着,什么也不做。直到第一个人心里计数到99时,说明所有人已经到过。即可向国王证明。  
   
  class   Class1  
  {  
  ///   <summary>  
  ///   アプリケーションのメイン   エントリ   ポイントです。  
  ///   </summary>  
  [STAThread]  
  static   void   Main(string[]   args)  
  {  
   
  bool   flag;  
  flag=false;  
  int   count;  
  int   zo;  
  zo=0;  
  count=0;  
  Qiu[]   ks=new   Qiu[100];  
  int   loc;  
  Random   ra   =new   Random   ();  
  int   top;  
  top=0;  
  do    
  {  
  loc=   ra.Next(100);  
   
  if   (zo++==0)  
  {  
  top=loc;  
  flag=true;  
  ks[top].active   =true;  
  ks[top].days   +=1;  
  }  
  else  
  {  
  if(loc==top)  
  {  
  if(!flag)  
  {  
  flag=true;  
  count++;  
  ks[top].days   +=1;  
   
  }  
  else  
  {  
  ks[top].days   +=1;  
  }  
  }  
  else  
  {  
  if(flag   &&   (ks[loc].active   ==false))  
  {  
  flag=false;  
  ks[loc].active   =true;  
  ks[loc].days   +=1;  
  }  
  else  
  ks[loc].days   +=1;  
  }  
   
  }  
  }while   (count<99);  
  System.Console.WriteLine(zo.ToString   ());  
  System.Console.WriteLine(count.ToString   ());  
  System.Console.WriteLine(top.ToString   ());  
  for   (int   i=0;i<100;i++)  
  {  
  System.Console.WriteLine   ("No."+i   +":     "+ks[i].days   );  
  }  
  }  
   
  struct   Qiu  
  {  
  public   int   days;  
  public   bool   active   ;  
  }  
  }  
  Top

18 楼kkbspod(我被可乐淹死了)回复于 2006-04-06 14:56:07 得分 0

某次运行结果  
   
  11004  
  99  
  95(第一次出去的人)  
  No.0:     104  
  No.1:     128  
  No.2:     110  
  No.3:     103  
  No.4:     105  
  No.5:     107  
  No.6:     115  
  No.7:     108  
  No.8:     122  
  No.9:     127  
  No.10:     95  
  No.11:     113  
  No.12:     119  
  No.13:     119  
  No.14:     105  
  No.15:     121  
  No.16:     110  
  No.17:     96  
  No.18:     108  
  No.19:     102  
  No.20:     109  
  No.21:     107  
  No.22:     113  
  No.23:     110  
  No.24:     126  
  No.25:     115  
  No.26:     106  
  No.27:     98  
  No.28:     106  
  No.29:     88  
  No.30:     102  
  No.31:     112  
  No.32:     106  
  No.33:     111  
  No.34:     106  
  No.35:     102  
  No.36:     97  
  No.37:     109  
  No.38:     89  
  No.39:     132  
  No.40:     108  
  No.41:     111  
  No.42:     118  
  No.43:     103  
  No.44:     102  
  No.45:     112  
  No.46:     86  
  No.47:     121  
  No.48:     132  
  No.49:     96  
  No.50:     112  
  No.51:     112  
  No.52:     117  
  No.53:     104  
  No.54:     102  
  No.55:     113  
  No.56:     123  
  No.57:     81  
  No.58:     119  
  No.59:     118  
  No.60:     132  
  No.61:     101  
  No.62:     102  
  No.63:     96  
  No.64:     110  
  No.65:     120  
  No.66:     95  
  No.67:     99  
  No.68:     109  
  No.69:     120  
  No.70:     97  
  No.71:     105  
  No.72:     120  
  No.73:     122  
  No.74:     111  
  No.75:     127  
  No.76:     108  
  No.77:     109  
  No.78:     125  
  No.79:     140  
  No.80:     109  
  No.81:     110  
  No.82:     104  
  No.83:     128  
  No.84:     123  
  No.85:     105  
  No.86:     108  
  No.87:     101  
  No.88:     95  
  No.89:     116  
  No.90:     115  
  No.91:     85  
  No.92:     110  
  No.93:     103  
  No.94:     118  
  No.95:     111  
  No.96:     103  
  No.97:     121  
  No.98:     111  
  No.99:     129Top

19 楼tykmn(C&J)回复于 2006-04-06 15:16:36 得分 0

kkbspod(我被可乐淹死了)   ,^_^,好的,跟我的想法一样。Top

20 楼jinjiajie(leorio)回复于 2006-04-06 17:29:48 得分 0

...果然是好办法...天才呀,哎,这个就代表某人要放出去100次才行.....100个人轮到他,放出去100次,基本上人都快死绝了...Top

21 楼CGSK(双鱼座、清心斋、避忧塘。)回复于 2006-04-06 17:44:39 得分 0

可乐办法挺好呢。Top

22 楼jruv(~~~一叶落而知天下秋~~~)回复于 2006-04-07 00:02:14 得分 0

可乐的办法的确可以证明,   但是平均下来都要30年后才能证明,等于终生监禁了,还有什么意义吗。期待更好的答案Top

23 楼blueslmj(谁比我菜)回复于 2006-04-07 13:20:30 得分 0

好像只有这个办法了     等看还有天才出现没...Top

24 楼kevinmartin(海魂)回复于 2006-04-07 13:37:32 得分 5

好像确实没有别的办法了,被选定的人还不仅仅会被放出去100遍,而是超过100次,平均下来大概是28年多……,下次让国王别选这么多人了。50个人也够受的了。Top

25 楼oybee(oybee)回复于 2006-04-07 15:48:08 得分 0

这题有点意思~Top

26 楼yleiou(单刀匹马)回复于 2006-04-07 16:43:44 得分 0

可乐的办法可行Top

27 楼iamdavid0123(努力会有回报吧)回复于 2006-04-07 17:25:19 得分 0

可乐弓虽Top

28 楼iamdavid0123(努力会有回报吧)回复于 2006-04-07 17:26:09 得分 0

可了好像C#做的吧,赫赫Top

29 楼kkbspod(我被可乐淹死了)回复于 2006-04-07 19:07:13 得分 0

呵呵,确实是c#   好几年没有用过c/c++了,忘的差不多了。Top

30 楼BKgHost(黑色幽灵)回复于 2006-04-08 12:33:04 得分 0

这个办法编程可行,实际就玩完了Top

31 楼tatbaby(岛主)回复于 2006-04-08 12:45:56 得分 0

markTop

32 楼chen8314(跳蚤陈)回复于 2006-04-08 13:12:34 得分 0

想想~~~~Top

33 楼nextel(一切都只是感觉!)回复于 2006-04-08 13:21:32 得分 0

呵呵。有意思Top

34 楼A_B_C_ABC(黄瓜@YouCanDoIt)回复于 2006-04-08 14:06:42 得分 0

kkbspod(我被可乐淹死了)   解决问题的思路正确,但程序结构不是很好  
   
  do循环中if   (zo++==0){...}   zo只在最开头等于0,其他万多次循环的判断是浪费资源。  
   
  这个if的else里的另一个if...else...也有可改进的地方  
  Top

35 楼zijida(左八荣,右八耻,代表挂腰间,和谐贴胸前,人挡杀人,佛挡杀佛!)回复于 2006-04-08 18:32:50 得分 10

"不管起始如何,让第一个出去的人(也就是第一天出去的人)把电灯置于开的状态。"  
   
  根据资料,谁是第一个出去的人,是无法判断的.  
  假设关进去不久(因为无法准确判断时间,一天和两天差别不大),一个人第一次出去发现灯是开状态,那他做什么决定好呢?  
  是假设自己是第一人,还是顺手把灯关掉?Top

36 楼zijida(左八荣,右八耻,代表挂腰间,和谐贴胸前,人挡杀人,佛挡杀佛!)回复于 2006-04-08 18:45:40 得分 10

short   jailbird[100];  
  short   spyer   =   50;                       //指定固定的监测人  
  short   prisoner_air   =   0;  
  short   spycount   =   0;  
   
  short   lampstart   =   rand()%2;  
  short   curlamp   =   lampstart;  
   
  unsigned   int   days   =   0;  
  for(int   i   =0;i<100;i++)   jailbird[i]=0;  
   
  while(spycount   <99)  
  {  
  prisoner_air   =   rand()%100;  
  if(prisoner_air   ==   spyer)  
  {  
  if(   curlamp   ==1   )    
  {  
  curlamp   =   0;  
  spycount   ++;  
  }  
  else{}  
  }  
  else   if(jailbird[prisoner_air]   ==   0)  
  {  
  if(curlamp   ==   0   )  
  {  
  curlamp   =   1;  
  jailbird[prisoner_air]=1;  
  }  
  }  
  else  
  {  
  }  
  days   ++;  
  printf("day   %d:   the   jailbird   %d   let   to   fresh   air.   \n",days,prisoner_air);  
  }  
   
  printf("it's   spend   them   %d   days   to   complement   the   attestent!",days);  
  getchar();  
  return   0;Top

37 楼erwa(二娃)回复于 2006-04-08 20:48:42 得分 0

这么难还专门叫新手做`~?~?Top

38 楼sumnet(每天我都在进步因为我从没想过要放弃)回复于 2006-04-08 20:54:23 得分 0

在心里加1是什么意思  
  他知道他前面有多少个人出去了??Top

39 楼daidodo(火箭发射机)回复于 2006-04-08 21:03:54 得分 0

mark  
  Top

40 楼yjm0105(流云)回复于 2006-04-08 21:27:17 得分 10

#include   <iostream>  
  #include   <ctime>  
  using   namespace   std;  
   
  int   main()  
  {  
  char   light;  
  int   anyone,mealCount=0;  
  const   int   PriNum=100; /*囚犯人数*/  
  const   int   GuessNum   =   30; /*最多剩下1个人的时候,放风次数最多的人的大概放风次数*/  
  int   seq[PriNum]; /*标记每囚犯放风次数(第20顿饭之后)*/  
  int   lastSeeLighOn[PriNum]; /*囚犯最后一次见到灯亮是自己第几次放风(第20顿饭之后)*/  
  memset(seq,0,sizeof(seq));  
  memset(lastSeeLighOn,-1,sizeof(lastSeeLighOn));  
  srand(   (unsigned)time(   NULL   )   );  
  light=rand()%2; /*   随机初始化灯的状态*/  
   
  cout<<"the   sequence   number   of   every   prisoner's   outing(after   the   20th   meal):"<<endl;  
  while(1)  
  {  
  if(mealCount<=20   ) /*前20顿饭的时间之内,无论谁如果看到灯亮,都灭了它*/  
  {  
  mealCount++;  
  if(light)  
  light=0; /*保证第20顿饭之后灯处于灭的状态*/  
  }  
  else  
  {  
  anyone=rand()%PriNum; /*随机抽取囚犯放风*/  
  if(!seq[anyone]) /*该囚犯是第一次放风*/  
  {  
  light=(light+1)%1; /*改变灯的状态*/  
  cout<<anyone+1<<'\t';  
  }  
  seq[anyone]++; /*该囚犯放风次数加1*/  
  if(light)  
  lastSeeLighOn[anyone]=seq[anyone]; /*记住自己最后见到灯亮是第几次放风*/  
  if(seq[anyone]>GuessNum   &&   light   ==   0   ) /*有人放风超过GuessNum次了*/  
  {  
  if(   lastSeeLighOn[anyone]<   GuessNum/2   ) /*最后连续至少GuessNum/2次看到灯灭了*/  
  {  
  /*到现在,灯是灭的,只可能  
  ①PriNum   个囚犯都看过了;  
  ②   还有   2   个囚犯   一次都没出来过;    
    当GuessNum足够时,万一的情况也就是还有1个倒霉鬼没出来过,但是  
  基于灯灭的情况,还剩2个倒霉鬼是几乎不可能存在的----这跟GuessNum的  
  取值有些关系,当GuessNum合适时,我们可以认为现在属于情况①:都放过风了,  
  所以,我们出狱吧-------如果确实出现了②的情况,我们也认了,好过于坐到老死@@*/  
  cout<<"\nOK,let's   go!   ----NO."<<anyone+1<<endl;  
  break;  
  }  
  }  
   
  }  
  }  
  for(int   i=0;i<PriNum;i++)  
  cout<<"NO."<<i+1<<":   "<<seq[i]<<"times\t";  
  cout<<endl;  
   
  return   0;  
  }  
  Top

41 楼yelingzj(野灵)回复于 2006-04-08 21:35:13 得分 0

这个问题很有意思,只是我不会啊!Top

42 楼A_B_C_ABC(黄瓜@YouCanDoIt)回复于 2006-04-08 23:46:49 得分 0

yjm0105(流云)   你   这句想干嘛?  
   
  light=(light+1)%1; /*改变灯的状态*/Top

43 楼yjm0105(流云)回复于 2006-04-08 23:58:20 得分 0

是这样的  
  A.前20顿内   使灯灭light=0;  
  B.之后,按每人第一次放风为序;  
  C.第奇数个首次放风的人,开灯light=1;  
  D.第偶数个首次放风的人,关灯light=0;  
   
  所以,足够次数后,如果还有1个人没得到放风机会,灯一定是亮着的...  
  Top

44 楼A_B_C_ABC(黄瓜@YouCanDoIt)回复于 2006-04-09 00:29:47 得分 0

light=(light+1)%1;       light永远为0耶Top

45 楼ox_thedarkness()回复于 2006-04-09 01:07:41 得分 10

同意   zijida(深水游鱼,吐泡泡被追殴.。o   0)   (   )   的看法  
   
  既然有:  
   
   
  “每人一间牢房,都与外界隔绝,什么也听不见、看不到,连时间都没法计算,更别说获得外界的任何信息。(送饭除外,但也是不规律的送)”  
   
   
  那么谁知道自己是第一个人呢?Top

46 楼ox_thedarkness()回复于 2006-04-09 01:10:42 得分 0

-     -   不过如果可乐的是正确答案  
  那么这个问题够狠啊,实际上就是判他们终生监禁了,而且任何一个囚犯出一个失误(不管是有意的还是无意的)都全挂...   偶劝他们挖地道越狱把...Top

47 楼yjm0105(流云)回复于 2006-04-09 09:01:44 得分 0

-----------------------------------------------------------------------  
  A_B_C_ABC(黄瓜)   (   )   信誉:100     2006-04-09   00:29:00     得分:   0        
     
        light=(light+1)%1;       light永远为0耶  
  -----------------------------------------------------------------------  
  不好意思,不留神打错了m_!  
   
  应该是:light=(light+1)%2;Top

48 楼yjm0105(流云)回复于 2006-04-09 09:02:32 得分 0

#include   <iostream>  
  #include   <ctime>  
  #include   <conio.h>  
  using   namespace   std;  
   
  int   Simulation()  
  {  
  int   light; /*灯状态:0灭   1亮*/  
  int   daysPast=0; /*经过的天数*/  
  int   anyone; /*囚犯的编号*/  
  int   proveOne; /*最后出场证明的囚犯编号*/  
  int   mealCount=0; /*吃饭的顿数*/  
  const   int   PriNum=100; /*囚犯人数*/  
  const   int   GuessNum   =   30; /*最多剩下1个人的时候,放风次数最多的人的大概放风次数*/  
  int   seq[PriNum]; /*标记每囚犯放风次数(第20顿饭之后)*/  
  int   lastSeeLighOn[PriNum]; /*囚犯最后一次见到灯亮是自己第几次放风(第20顿饭之后)*/  
  memset(seq,0,sizeof(seq));  
  memset(lastSeeLighOn,-1,sizeof(lastSeeLighOn));  
  srand(   (unsigned)time(   NULL   )   );  
  light=rand()%2; /*   随机初始化灯的状态*/  
  cout<<"Init   :   light   =   "<<light<<endl;  
  cout<<"the   sequence   number   of   every   prisoner's   outing(after   the   20th   meal):"<<endl;  
   
  while(1)  
  {  
  daysPast++; /*天数加1*/  
  if(mealCount<=20   ) /*前20顿饭的时间之内,无论谁如果看到灯亮,都灭了它*/  
  {  
  mealCount++;  
  if(light)  
  light=0; /*保证第20顿饭之后灯处于灭的状态*/  
  }  
  else  
  {  
  anyone=rand()%PriNum; /*随机抽取囚犯放风*/  
  if(!seq[anyone]) /*该囚犯是第一次放风*/  
  {  
  light=(light+1)%2; /*改变灯的状态*/  
  cout<<anyone+1<<'\t';  
  }  
  seq[anyone]++; /*该囚犯放风次数加1*/  
  if(light)  
  lastSeeLighOn[anyone]=seq[anyone]; /*记住自己最后见到灯亮是第几次放风*/  
  if(seq[anyone]>GuessNum   &&   light   ==   0   ) /*有人放风超过GuessNum次了*/  
  {  
  if(   lastSeeLighOn[anyone]<   GuessNum/2   ) /*最后连续至少GuessNum/2次看到灯灭了*/  
  {  
  /*到现在,灯是灭的,只可能  
  ①PriNum   个囚犯都看过了;  
  ②   还有   2   个囚犯   一次都没出来过;    
    当GuessNum足够时,万一的情况也就是还有1个倒霉鬼没出来过,但是  
  基于灯灭的情况,还剩2个倒霉鬼是几乎不可能存在的----这跟GuessNum的  
  取值有些关系,当GuessNum合适时,我们可以认为现在属于情况①:都放过风了,  
  所以,我们出狱吧-------如果确实出现了②的情况,我们也认了,好过于坐到老死@@*/  
  proveOne=anyone;  
  cout<<"OK,let's   go!   ----our   every   times   is:\n";  
  break;  
  }  
  }  
   
  }  
  }  
  int   min=0xffff,max=0;  
  for(int   i=0;i<PriNum;i++)  
  {  
  min=min   >   seq[i]   ?   seq[i]   :   min;  
  max=max   <   seq[i]   ?   seq[i]   :   max;  
  cout<<"NO."<<i+1<<":       "<<seq[i]<<"\t";  
  }  
  cout<<"\nThe   proveOne   is   NO."<<proveOne+1<<endl;  
  cout<<"past   days   :   "<<daysPast<<endl;;  
  cout<<"the   max   times   is   "<<max<<"   and   the   min   times   is   "<<min;  
  return   0;  
  }  
  int   main()  
  {  
  while(1)  
  {  
  system("cls");  
  Simulation();  
  if(getch()==0x0d)  
  {  
  cout<<endl;  
  break;  
  }  
  }  
   
  return   0;  
  }Top

49 楼vcmute(BCare4 H1Rest Good9!)回复于 2006-04-09 09:15:40 得分 0

as   aboveTop

50 楼lonelyforest(一生所爱)回复于 2006-04-09 09:29:26 得分 0

不知道又是那个BT公司的面试题目Top

51 楼yjm0105(流云)回复于 2006-04-09 09:36:14 得分 0

看了   可乐   的办法,在理论上似乎可行,,然而实际上是不行的:  
  1.不能确定谁是第一个放风的人  
  2.可能指定的这个人一生就出去这么几次(总之小于99次)  
  3.时间太长,不知道到时候还剩几个人在  
   
  虽然可以预先指定一个人作为证明人,再在前n顿饭的时间内像我那样初始化灯为灭的状态,放风次数从n顿之后开始计算,然则   2、3两点仍然无法解决.  
   
  显然,这题根本无法100%保证能让囚犯们获得释放(要考虑现实时间)  
   
  我的办法可以在较短的时间使他们被释放(假如不出现那极小可能的话,但要想避免这个可能,时间上大概是不允许的,因为就算按顺序轮着放风,也得大约30年时间),我想囚犯们听了我的意见后一定会觉得这是可行的,这个赌博赢的可能太大了----Top

52 楼erwa(二娃)回复于 2006-04-09 10:27:37 得分 0

哦!!  
                  懂拉`   `这题真的很难啊`1!Top

53 楼erwa(二娃)回复于 2006-04-09 10:32:37 得分 0

但是可乐你是用了想出来的这种方法的啊?~?~  
                  我想拉一下午最后觉得根本没答案哈哈`看来以后想问题不能这么轻率了   `Top

54 楼sjjf(水晶剑锋)回复于 2006-04-09 19:13:00 得分 7

我觉得跟灯没有关系,  
  不知道我的理解是否正确。  
   
  如果能够判断谁是第一个人,那么也就能够判断谁是最后一个人。  
  有最后一个人出来说就行了。  
  因为对于每一个人来说,每一次都是无状态的,判断不了,那么这种方案就不可行。  
   
  ============================  
  每天会随机打开一间牢房的门  
  ============================  
  不知道允不允许重复。  
   
  如果允许的话,那么这道题不存在绝对解,随机的含义很明显,有可能有一个人永远也轮不到。  
  在这种情况下,没有谁可以拿出一个方案来证明所有人都放过风,如果能拿出来,就意味着他是错误的。当然,随着个体出去放风的次数也多,他能推断所有人的都出去过的概率也就越大,  
  但是概率始终是概率,不是确定性的东西。除非他们不珍惜生命了,否则选择一直呆下去会比选择证明会好一点。  
   
   
  如果在每100次的遍历(打开门)中。不允许重复。那么解法很简单,谁第一个两次出去的人就能够证明所有人都出去放过风。而且花费200天的时间,所有的人都能够证明。  
  如果是这种做法的话,函数也很简单,每个人维护一个人累计值,到达2的时候出去跟国王说就行了。  
   
   
  Top

55 楼huangyb00(金月飙)回复于 2006-04-09 20:14:28 得分 0

第一个人根本就无法确定,所以必须先指定一个,但是这样好象的是最好的方法!Top

56 楼pyuanq(大狼)回复于 2006-04-09 20:47:55 得分 0

看来二十颗人头要落地了。Top

57 楼shengmingzi(唐宝马)回复于 2006-04-10 00:56:11 得分 5

只要“自圆其说”就可以了嘛。  
  那个记数的人只需要等到200多天以后就可以去跟国王说:  
  “我已经出去放风100次,每次出去的时候灯都是开着的,我已经关灯100次了”  
  国王如果问其他的人,他们只要回答:  
  “我只出去过一次,每次出去,灯都关着,我把它打开了。”  
  不过概率是50%(如果开始灯是关着的,那关灯100次就是说谎了,哈哈),值得赌一下。Top

58 楼cattlenzq(吃狼的豆腐(不要给分了,散起来真麻烦!))回复于 2006-04-10 01:50:48 得分 5

to   yjm0105(流云)   (   )   信誉:100  
  怎么才能知道自己是奇数个还是偶数个??  
   
  因为说是每天一个人,所以肯定可以得到有人很快就能进去,但是没有说是不是下一天(感觉是第二天就有人进去了),可以试下,吃饭次数在1000次以内的时候不管谁进去都把灯关了,1000次以后这样做(我就不信国王能白喂他们1000顿不放一个人出去。靠!!!)  
   
   
  一个人只管把灯开开;  
  其他的人只管关灯(如果灯关着就不动他,等下次出来)  
   
  数到99,就可以肯定的向国王报告了。Top

59 楼pansy10(长风)回复于 2006-04-10 04:41:35 得分 5

把一百个人编号,当天放出去的人编为N,如果他是第一次放风,刚把灯打开N次,其它人计数,如果发现从1到100次都闪过了,就可以找国王啦  
   
  灯初始是关。设一个bitset变量flag,一百个人编号,  
  每一天{  
  当天随机选出去的人编号N,然后把flag的第N位置1  
  flag所有位都为1?break:   ;  
  }Top

60 楼pansy10(长风)回复于 2006-04-10 04:44:57 得分 0

我错了。灯光他们看不到。。Top

61 楼hsilz(三星五角▲▲▲★★★★★自己加星玩)回复于 2006-04-10 09:22:52 得分 1

真的无法判断谁是第一个。  
  即便是什么前1000顿饭都出去把灯关掉也不行。  
  因为你不知道当天是先吃饭还是先放风。  
   
  要是把这个问题解决了,就可以了Top

62 楼fyydkdk(猪2虫)回复于 2006-04-10 10:29:07 得分 0

方法很多,就看看哪个的算法最好了!!!  
  Top

63 楼cattlenzq(吃狼的豆腐(不要给分了,散起来真麻烦!))回复于 2006-04-10 10:46:12 得分 1

不需要知道谁是第一个,只要一段时间出去的人都把灯关了就可以了,因为无法知道具体时间,只能靠送饭的次数来判断大概的时间,1000顿饭以内只要有1个或者1个以上的人出去就可以了,那样就可以把灯的状态改成关,下来再进行判断,以前的只是准备工作。  
   
  如果1000顿饭以内可能会出现没有一个人被拉出去放风的情况,那么就10000000000000000000顿  
  Top

64 楼ghostzf()回复于 2006-04-10 13:29:17 得分 0

能不能用取模法和0,1状态提高效率?Top

65 楼A_B_C_ABC(黄瓜@YouCanDoIt)回复于 2006-04-10 16:47:21 得分 0

贴主发言:  
   
  1)关于灯的初始状态和谁是第一个放风的人  
  只要确定了灯的初始状态,那么不需要知道谁是第一个放风的人.比如若囚犯们都知道灯的初始状态为关,任意指定一个人负责开灯,其他人只要看到灯开了且自己又没关过灯,则关闭灯;开灯的人看到灯关了就肯定有一个没出来过的人出来过了。其实这只是个如何合理计数的问题,所以发贴时要求是新手做,有经验的人可能会觉得没意思。  
  那么如何确定灯的初始状态,yjm0105(流云)的方法就可行。10顿饭或20顿饭之前出来的人可以设置灯的初始状态,如为关。以后必须等到20顿饭后开灯人开了灯后,其他人才会关,关了后开灯人一定会看到,从而计数。至于“这整个过程需要长达30年左右的时间,会不会有人挂了,从而永远不能计数”这类问题,不是这里应该考虑的。因为囚犯没法计算时间,国王完全可以一天在不同的时间随机让若干个囚犯单独放风,而问题的实质不会改变,但整个过程所需的时间却大大减小了。  
  2)若能确定第一个放风的人,那么囚犯们不需要知道灯的初始状态。  
  第一个放风的人自动成为计数人,并把灯置为关,其他人只要看到灯关着且自己没开过灯,则开灯。前面几人给出的程序就是按这个思路写的。但若严格按题意,若灯的初始状态囚犯们也不知道,那么囚犯们是不能自我确定是否是第一个放风的人的。   所以按这个思路解答的人,可以认为题目加了这样一个限制:“囚犯们知道白天黑夜,且每天随机的必有仅有一个囚犯放风”   。Top

66 楼sjjf(水晶剑锋)回复于 2006-04-10 17:32:42 得分 0

我关心的是,所谓的随机,有没有重复?  
  就是说在开始的100天(或者次)内,是不是每人有且只有一次机会。  
  如果是,第一个两次出来的人跳出来就是答案了。  
  如果不是,那么这道题应该没有答案,因为存在着有人永远没有放风机会的情况。  
  只要有这种情况存在,就没有方法证明在有限的次数内,所有人都出来过。Top

67 楼zijida(左八荣,右八耻,代表挂腰间,和谐贴胸前,人挡杀人,佛挡杀佛!)回复于 2006-04-10 18:39:48 得分 0

这个问题有两个关键部位:  
    1.如何快而精确地确定灯的初始状态.  
    2.能不能在囚犯中动态指定证明人.  
   
          关于第1点,从题目给定的内容来理解,灯的初始状态不定,通过按吃饭顿数来设置灯的初始状态,是一个很别致的想法,但是很遗憾,从题目给定内容中没有明确指出:所有犯人的吃饭时间是同步的.有人给出的200,2000,2000...顿之后灯肯定是被初始化过了,这是对的.但这种计吃饭顿数的方法,对于第2点毫无帮助.  
   
        关于第2点,如果灯的初始状态是已知的,那么第一个出来看到灯的状态和初始状态一致的人自动就成为证明人,这是可行的,但接下来的工作就无法进行了,因为这里有一个致命的问题:他无法把证明人已经产生的事实通知到所有人.试想,他按照约定改变了灯的状态,然后第二个放风的人发现灯的状态改变,他知道证明人产生了.但接下来怎么办呢?按照约定,他又把灯的状态切换了...然后第三个放风人发现灯的状态是初始状态...然后一切都乱了.  
   
  所以说:  
   
  "只要确定了灯的初始状态,那么不需要知道谁是第一个放风的人..."  
   
  这种思路有问题,在确定的灯的初始状态的情况下,仍然需要指定固定的证明人.除非有方法让所有囚犯都得到通知:证明人产生了!Top

68 楼zijida(左八荣,右八耻,代表挂腰间,和谐贴胸前,人挡杀人,佛挡杀佛!)回复于 2006-04-10 18:53:55 得分 0

"关于第2点,如果灯的初始状态是已知的,那么第一个出来看到灯的状态和初始状态一致的人自动就成为证明人,这是可行的,但接下来的工作就无法进行了,因为这里有一个致命的问题:他无法把证明人已经产生的事实通知到所有人.试想,他按照约定改变了灯的状态,然后第二个放风的人发现灯的状态改变,他知道证明人产生了.但接下来怎么办呢?按照约定,他又把灯的状态切换了...然后第三个放风人发现灯的状态是初始状态...然后一切都乱了."  
   
  这个我再解释一下:第三个放风人是不能确定在他之前是否有人放过风的,如果他把自己当成证明人,整个过程中就出现了两位证明人,而证明人的工作就是每次放风时把灯切换到指定状态,这样两个证明人之间就产生了干扰,如果恰好每次两人都被交替连续放出,过程就产生了死锁.以此类推,还会产生三个,四个...证明人的情况!Top

69 楼sjjf(水晶剑锋)回复于 2006-04-10 19:14:12 得分 0

lz在那儿看得题?  
  有没有答案?  
  偶感觉这道题似乎说不通。  
   
  还有那个随机是怎么个随机法请说明一下。Top

70 楼A_B_C_ABC(黄瓜@YouCanDoIt)回复于 2006-04-10 20:02:35 得分 0

我关心的是,所谓的随机,有没有重复?  
  就是说在开始的100天(或者次)内,是不是每人有且只有一次机会。  
  如果是,第一个两次出来的人跳出来就是答案了。  
  如果不是,那么这道题应该没有答案,因为存在着有人永远没有放风机会的情况。  
  只要有这种情况存在,就没有方法证明在有限的次数内,所有人都出来过。  
  ====================================  
  所谓的随机,指任何时候,任何人都有机会放风。即开始的100天内,有人可能不只一次放风,有人得不到放风。但随着时间的增加,有人得不到放风的可能越来越小,即有人放风50次,有人却不能放风,这种可能性理论上有,但实际上没有,就象丢硬币的正反面,理论上连续50次正面都有可能,但这种可能小得在实际中根本不会出现。所以不存在没有答案。  
  如果囚犯平均每人放风100次,那么放风大于100次和小于100次的人数差不多。我们以放风次数为横坐标,即81次,82次,83次......118次,119次,120次为横坐标,以人数为纵坐标,即在这个坐标系统中画出放风81次对应的人数坐标点,放风82次对应的人数坐标点,(在该次上没有对应的人数的点不管)   ......最后连接这些点,所得到的曲线是一个中间高两头低,象一个古钟(编钟)一样。这个曲线,凡是学个概率的都应见过。它说明,如果所有人放风平均100次,那么有人放风200次和有人放风0次的概率趋近于0,甚至有人放风150次和有人放风50次的概率也非常小。     所以,无论我们指定谁为计数人,他总能到达放风100次,而其他人放风的次数也不至于和他相差很多。  
  Top

71 楼A_B_C_ABC(黄瓜@YouCanDoIt)回复于 2006-04-10 20:20:38 得分 0

关于第2点,如果灯的初始状态是已知的,那么第一个出来看到灯的状态和初始状态一致的人自动就成为证明人,这是可行的,但接下来的工作就无法进行了,因为这里有一个致命的问题:他无法把证明人已经产生的事实通知到所有人.试想,他按照约定改变了灯的状态,然后第二个放风的人发现灯的状态改变,他知道证明人产生了.但接下来怎么办呢?按照约定,他又把灯的状态切换了...然后第三个放风人发现灯的状态是初始状态...然后一切都乱了.  
   
  所以说:  
   
  "只要确定了灯的初始状态,那么不需要知道谁是第一个放风的人..."  
  ================================================================  
  “因为这里有一个致命的问题:他无法把证明人已经产生的事实通知到所有人.”  
  这里你理解错误。  
  如果灯的初始状态是已知的,那么囚犯们在入监狱前就已经决定由谁当这个计数证明人,比如说张三。现在假设囚犯们知道灯的初始状态为关,张三负责开灯,那么张三是不是第一个出来不重要,重要的是只有张三出来灯才会开,之后,若有没关过灯的囚犯出来就会把灯关闭,再之后,只要不是张三出来,其他人什么也不会做,只要张三一出来,看到灯关了,那么它知道一定有一个没放过风的兄弟出来过了,。。。如此往复,张三能肯定有多少兄弟出来过了。  
  Top

72 楼sjjf(水晶剑锋)回复于 2006-04-10 20:38:16 得分 0

关于你对概率的观点,我不同意把小概率事件当作确定性的事件,  
  按照你的说法。还是基于不确定的猜测上。而不是确定的推算上。  
  因为如果张三永远也没有机会出来放风呢?或者只有不到100次的机会出来,  
  那么所有的人都得呆在那里。Top

73 楼A_B_C_ABC(黄瓜@YouCanDoIt)回复于 2006-04-10 20:53:04 得分 0

lz在那儿看得题?  
  有没有答案?  
  偶感觉这道题似乎说不通。  
   
  =============  
  这个提目的更多讨论请参见  
  http://dzh.mop.com/topic/main/readSubMain_6491044_-1.html  
  这个讨论的精华请参见  
  http://www.pmme.cn/?p=494  
   
  至于答案,我认为就是一个合理计数的问题,前面的回复已说明。如果用概率,那就是赌,胜算很大的赌。Top

74 楼yjm0105(流云)回复于 2006-04-10 21:00:08 得分 0

To:   cattlenzq(查无此人)   (   )   信誉:100    
        不需要知道自己是第奇数还是偶数个:  
  (1)初始化时段:假设为20顿饭的时间,谁出去都保证灯是关闭的;  
  (2)从第20(假设是20)顿饭之后计算,第2*n-1个第一次出去的开灯,第2*n个第一次出去的关灯(n=1,2,3,...,50);  
  (3)假设有个人已经出去次数达N次了(N够大,先假设N=30),而他在N/2次到N次这段时间里发现灯一直是关闭的,那么他认为都出去过了,于是去申请向国王报告...  
      另:我觉得20顿饭的时间应该是够的,不至于1天之内让你连吃20顿吧,要这么说的话,那国王可以派几十万人都每天来各送1颗米当作一顿饭,那连这唯一的条件也失去了,没发活了,国王不至于自己跟自己过不去吧...  
   
  To:   hsilz(三星五角   自己加星玩)   (   )   信誉:100    
          在初始化时段里,每天只有一个人出来放风,所以不会影响其他99人,  
  当你出来放风时:如还没吃过第20顿饭(假设是20),就使灯OFF;如吃过了,就另当别论(只需把灯置为相反状态即可);如果正在吃(不应该吧),那就当成是第21顿好了,然后把灯置ON...  
          如果是在20顿以后的时间里,不存在先后与否的问题.  
   
  To:   sjjf(水晶剑锋)   (   )   信誉:100    
          如按你说的100天内每人都出来一次,那本题就不是问题了吧.  
   
  To:   A_B_C_ABC(黄瓜)   (   )   信誉:100    
        楼主:  
        题目指明:"每天会随机打开一间牢房的门,让那个囚犯到院子里来放风",如果也可以理解为允许"某天打开不止一间"的话,那可真要来把每个字、词都从古到今的琢磨1E遍,我想题目一定漏洞何止百出了  
        不需要附加"囚犯们知道白天黑夜"的条件,题目已经说明是每天只放一个人而且不应该是多放几个.  
        虽然题目没有指明是否考虑时间,但我仍然认为时间值得考虑;而就算按顺序轮着放风,也得大约30年时间,如果乱序而且你们先指定的人很可能是出去不了99次的,那会产生方法引起的无解.  
        我认为这里的随机应该理解为大自然的随机,不能是由国王来指定每天给那个放风,那样全部的希望又回到了国王的手里,想必国王也不是笨蛋,何必多此一举,故意做作...虽然我也无法保证100%就能把他们都释放了,但这是一个赢面极高的赌注,赌的是足够时间后最多还有1个人没出来过(这样,灯由ON转OFF后,某个达到设定次数的人就可以向国王报告了),如果真要出现2个人一起都没出来过,天意如此,只有OVER了---没办法我真的没办法啦@@  
  Top

75 楼yjm0105(流云)回复于 2006-04-10 21:04:07 得分 0

To:   hsilz  
   
  你后面跟的几个三角五星可把我整惨了,害的我前一贴连打了2次字  
   
  居然说我发表有害言论,我一回退打的字也还是没有,郁闷,我伤害谁了@@  
  把你后面跟的那几个符号去了后就打出来了,ft......Top

76 楼A_B_C_ABC(黄瓜@YouCanDoIt)回复于 2006-04-10 22:55:04 得分 0

to   yjm0105(流云)    
   
  怪我没说好,导致你误解了我的意思。我的意思不是把:"每天会随机打开一间牢房的门,让那个囚犯到院子里来放风",理解为允许"某天打开不止一间"。   我的意思是“算来完成计数的时间要大约30年”,但我们不必计较这个时间有多长,这不是问题的本质,重要的是可以完成这个准确的计数。如果当初出题人规定为:“每一天在不同的时间随机让若干个囚犯单独放风”,这个问题的本质依然一样,只是所需的时间大为缩短。  
   
  Top

77 楼ox_thedarkness()回复于 2006-04-10 23:00:47 得分 0

三角五星....汗....Top

78 楼A_B_C_ABC(黄瓜@YouCanDoIt)回复于 2006-04-10 23:40:06 得分 0

To:   sjjf(水晶剑锋)    
   
  前面我说过:  
  “无论我们指定谁为计数人,他总能到达放风100次,而其他人放风的次数也不至于和他相差很多”  
  这不是“把小概率事件当作确定性的事件”,而是基于这样的理由:  
  既然是随机,那么“每天会随机打开一间牢房的门,让那个囚犯到院子里来放风”就是  
  每一天每个人放风的机会都有1%,而以前是否放过风并不影响这次放风的概率1%.      
  那么,100天内这100人中有人没有放过风是肯定的,两百天三百天有人没有放过风是可能的,但1000天2000天有人没有放过风是不太可能的,除非是人为,不是随机。那么所有人平均每人放风100次,而有人一次也没有或者很少,不符合“每一天每个人放风的机会都有1%”这个前提。  
   
  实际上,每人被放风的次数是随机交替上升的,即在某一时段,某人放风的次数可能是所有人中最少,但再隔一段时间他的放风次数可能会超过平均数,甚至有机会达到最高。不信的人可以用计算机产生的随机数模拟,如果你觉得计算机产生的随机数是伪随机数,不够说服力,请研究一下体彩,福彩产生的数字。  
  Top

79 楼ox_thedarkness()回复于 2006-04-11 00:04:30 得分 0

但是楼上的做法不是数学严格的证明阿。   从数学上说,一个事件无论概率多么小,只要概率不为0,这仍然是可能事件。   国王要求的也是数学严格的。  
   
  从这一点说,我认为无法给出初始条件,并且无法正确解决。    
   
   
  关键是题目要求“无法计时”  
   
  不过   ——   如果一定程度的“计时”,比如估计“超过100天”是能够办到的话,可以反过来这么做:  
   
   
  1   前几天的人   ——   无论它是谁,他负责开灯。如果灯是开的那么就让它开着。由于肯定有第一个人开灯所以这个肯定能办到。  
   
   
  2   然后大家等到一个远远超过“前几天”的状态,比如“第100天”开始,按照之前我们说的,由“仲裁者”负责关灯和计数。  
   
   
   
  这个的置信度比随机版本高得多。   唯一的问题在于,题目是否允许“感觉过了很长很长时间”Top

80 楼A_B_C_ABC(黄瓜@YouCanDoIt)回复于 2006-04-11 00:06:48 得分 0

有人说了,既然“1000天2000天有人没有放过风是不太可能的,除非是人为,不是随机。”,那么何必漫漫计数30年,我5000天报告国王说“我敢肯定所有的人都去过院子了,除非你没有随机放我们去院子”,这样也省了一半的牢狱之灾,保守点3000天应该也可以,要证据就每人出去时都下个灯泡或掰块开关。这也是个办法,但不是出题人的本意,3000天还是5000天也不是靠计算确定出来的,不能服众。Top

81 楼A_B_C_ABC(黄瓜@YouCanDoIt)回复于 2006-04-11 00:09:49 得分 0

有人说了,既然“1000天2000天有人没有放过风是不太可能的,除非是人为,不是随机。”,那么何必漫漫计数30年,我5000天报告国王说“我敢肯定所有的人都去过院子了,除非你没有随机放我们去院子”,这样也省了一半的牢狱之灾,保守点3000天应该也可以,要证据就每人出去时都下个灯泡或掰块开关。这也是个办法,但不是出题人的本意,3000天还是5000天也不是靠计算确定出来的,不能服众。  
  ===最关键的是题目限定了囚犯们不能计算过了多少天。Top

82 楼zijida(左八荣,右八耻,代表挂腰间,和谐贴胸前,人挡杀人,佛挡杀佛!)回复于 2006-04-11 09:01:50 得分 0

"如果灯的初始状态是已知的,那么囚犯们在入监狱前就已经决定由谁当这个计数证明人,比如说张三。"  
  -------------------------------------------------------------------------  
          这个说法我同意.也就是说,灯的初始状态不管是否确定,都需要在开始之前指定好证明人.如果灯初始状态不定,证明人需要置灯状态100次;如果初始状态已知,则可以少一次.Top

83 楼yjm0105(流云)回复于 2006-04-11 09:29:20 得分 0

如果总时间无限,那么可以揭贴了吧(指定报告人、灯的初始化次数就可以解决了)  
  如果总时间有限,那么数学上无解,概率只是概率,无法确定的推算一个值Top

84 楼sjjf(水晶剑锋)回复于 2006-04-11 10:36:39 得分 0

即使时间无限,也不存在确定解,无穷小不等同于0。  
  大数定理只是代表一种趋势,不代表就一定会这样。否则概率就没有意义了。  
   
  如果是非确定的话,有非确定性的解法。  
  也没必要去看什么灯之类的。看这些灯没有意义。  
  解法过几天贴上。Top

85 楼yjm0105(流云)回复于 2006-04-11 10:49:01 得分 0

to   sjjf(水晶剑锋)    
   
  你的意思是把灯拆了都能解,洗耳恭听.Top

86 楼A_B_C_ABC(黄瓜@YouCanDoIt)回复于 2006-04-11 12:50:16 得分 0

最后的程述  
   
  我的观点:  
  1)100天内这100人中有人没有放过风是肯定的  
   
  2)当100人平均每人放风100次,有人还没放过风是不可能的  
   
  3)无论我们指定谁为计数人,他总能到达放风100次,而其他人放风的次数也不至于和他相差很多  
   
  4)那种认为随机就是有人永远可能没机会出来     是错误的  
   
  至于道理,我的概率知识不够多,无法说服你们。  
   
   
  有时候按一种惯性思维看似简单的问题也会无解,比如这只兔子能否追上这只乌龟:  
  一只兔子每秒跑10米,一只乌龟每秒跑1米,兔子在乌龟的后面10米。二者同时向一个方向跑。  
  如果思考的人是这样想的:  
  兔子和乌龟相差10米,那么兔子跑完这10米,乌龟已向前跑了1米  
  兔子和乌龟相差1米,那么兔子跑完这1米,乌龟又向前跑了0.1米  
  兔子和乌龟相差0.1米,那么兔子跑完这0.1米,乌龟又向前跑了0.01米  
  .....  
  哇,好象兔子永远不能追上这只乌龟,因为它们之间相差的距离无论多么小,总是要相差那么一点点  
  可事实上兔子不用2秒就能超过乌龟很远啊,就是说追上乌龟是在一点几秒的时侯,但不能给出具体的时刻。  
  Top

87 楼za()回复于 2006-04-11 14:09:14 得分 1

楼上说的4条和兔子的例子完全不是一回事。  
   
  另外,从概率上说楼上的4点假设都是错误的。  
   
  虽然说小概率事件在一定条件下可以认为是不可能发生的,但在本题题面下是不能忽略的,因为必须“自圆其说”。Top

88 楼sjjf(水晶剑锋)回复于 2006-04-11 14:34:38 得分 0

也许偶说的可能早了点,  
  我需要去查一下概率的书中的公式才能做。忘了好多公式了。  
  这段时间忙,所以过几天才能给答案。  
   
  关于兔子和乌龟的那个还有什么飞矢不动的,在几百年前的希腊讨论的话还算时髦,  
  现在,几百年前的谬论我们就不要讨论了,  
  割裂时间和空间去讨论的没有什么意义。  
  如果要了解的话,可以去找一本叫什么<是是非非>什么悖论来的   儿童读物读一下吧。  
  我刚好去年买了一本送给我的一个亲戚的孩子,翻了一下,还挺有趣的,呵呵。  
  Top

89 楼bombwang(王)回复于 2006-04-11 14:41:30 得分 0

markTop

90 楼keats_zhang(冬日笑)回复于 2006-04-11 15:04:49 得分 0

mark   下  
  Top

91 楼za()回复于 2006-04-11 15:10:33 得分 0

有了微积分,兔子和乌龟问题就解了吧……Top

92 楼yjm0105(流云)回复于 2006-04-11 15:27:20 得分 0

黄瓜的4个观点,我一个也不同意.  
   
  关于乌龟和兔子的诡辩问题,“永远”是一个陷阱词,你按照他的方式去推理就只能落入陷阱,他把“永远”限制在兔子追上乌龟之前的时间里,照这么思考无论如何也突破不了那个极限,引用别人的一句话就是“兔子在兔子追上乌龟之前永远追不上乌龟”.Top

93 楼A_B_C_ABC(黄瓜@YouCanDoIt)回复于 2006-04-11 15:32:40 得分 0

有了微积分,兔子和乌龟问题就解了吧……  
  ================  
  这我知道,但引入了新知识新思路,不是象我那样一根筋地追下去Top

94 楼za()回复于 2006-04-11 16:08:46 得分 0

题目条件中指明“连时间都没法计算,更别说获得外界的任何信息。(送饭除外,但也是不规律的送)”,很显然不能不能依靠“天”和“顿饭”来辅助计数了。另外,灯的初试状态也是不定的。  
   
  我觉得在“灯的初试状态也是不定的”的条件下,因为当第一次放风的时候报告人无法确定之前是否有人已经动过开关了,所以此题无解。Top

95 楼Free_Wind22(还没想好...)回复于 2006-04-11 16:42:05 得分 0

mark  
  Top

96 楼fei8326(天际飞云)回复于 2006-04-12 22:42:40 得分 0

都是高手呀。看了计算机的问题果然是数学的问题呀!!!!  
  我回去再吧概率&离散弄一遍再来讨论这个吧Top

97 楼Error_Code(void)回复于 2006-04-13 22:57:40 得分 0

mark了Top

98 楼Error_Code(void)回复于 2006-04-14 11:59:53 得分 0

是个有意思的题目  
  想来想去好象就可乐那个解法     毕竟路灯只有两个状态  
  要是路灯有颜色状态   办法就多了     呵呵Top

99 楼he_sl(he_sl)回复于 2006-04-14 12:07:06 得分 0

markTop

100 楼pyyyyy(种地打鱼摸螃蟹)回复于 2006-04-14 13:58:06 得分 0

其实不用想,根据心理学,把人关在楼主所说的完全隔绝的房子里,过不了几天,会全部疯掉,根本不必做这个测试,哈哈,一刀杀了还痛快些,不过碗口大的疤。Top

101 楼GaoXX(窜天猴网络建筑队头子)(中窜集团)回复于 2006-04-16 03:03:06 得分 0

顶一下Top

102 楼DavidFu(寒羽)回复于 2006-05-16 19:07:02 得分 0

说说吃饭初始法的一个问题……  
   
  假设约定要把初始状态设置为关灯,  
   
  有X为记数人,A、B、C、D、……,送饭的时间从快到慢(没讲是一样吧?)为A、B、C、D、……X、……  
   
  当A吃完N次后,出来看到灯是关的,于是他/她(抗议认为囚犯只能是男性的性别歧视!)把灯打开,并认为自己已经开过灯了,以后不会再去开。  
   
  可是B还没吃完N次,就在A之后被放风了,于是他/她把按照初始化约定灯关了。  
   
  这样等X出来记数的时候,不是漏掉了A等若干吃饭快的家伙了……Top

103 楼DavidFu(寒羽)回复于 2006-05-16 20:39:11 得分 0

想到解决方案了。  
   
  就是在可乐方案的基础上,把每个人开灯的次数设为2次,而关灯计数人计到第198次的时候就可以确定99个人都出去过,不用考虑初始的那一次。Top

相关问题

关键词

得分解答快速导航

  • 帖主:A_B_C_ABC
  • du51
  • tykmn
  • kkbspod
  • kevinmartin
  • zijida
  • zijida
  • yjm0105
  • ox_thedarkness
  • sjjf
  • shengmingzi
  • cattlenzq
  • pansy10
  • hsilz
  • cattlenzq
  • za

相关链接

  • C/C++ Blog
  • C/C++类图书
  • C/C++类源码下载

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
世纪乐知(北京)网络技术有限公司 版权所有, 京 ICP 证 020026 号
北京创新乐知广告有限公司 提供技术支持
Copyright © 2000-2007, CSDN.NET, All Rights Reserved
GongshangLogo