yjm0105 阅读(756) 评论(3)

    国王招来100个囚犯,对他们说:你们犯的是死罪,本应该将你们统统杀掉,但我慈悲为怀,
给你们一次求生的机会。15分钟以后,你们将被关进一个有100间隔离牢房的监狱里,每人
一间牢房,都与外界隔绝,什么也听不见、看不到,连时间都没法计算,更别说获得外界的
任何信息。(送饭除外,但也是不规律的送)

    这所监狱有一个院子,每天会随机打开一间牢房的门,让那个囚犯到院子里来放风。院子里
有一盏路灯,放风的囚犯可以控制它的开关,将它打开或是关闭。除囚犯之外,
其他人都不会去碰开关。这盏灯会永远有充足的能源供应,如果灯泡坏了或是电路出了故障会马
上修好,当然修理人员不会改变灯的状态(开或关)。

    除了开关这盏灯,放风的囚犯放风时留下的任何其它痕迹都会在夜晚被清除干净(包括在灯上
作的任何记号)。

    牢房是完全封闭的,院子里的灯光在牢房里看不到。只有放风出到院子里的人才能看到。

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

    若干天以后,你们中只要有任何一个人能够向我证明所有的人都曾到院子里去过,你们就全体
释放。当然要有证据!因为我只会给你们一次机会,如果向我证明的那个人无法自圆其说,你们
就全部砍头。所以,要珍惜这次机会。如果你们永远做不到我的要求,你们就全部关到死.

    现在给你们15分钟商量你们的方案。15分钟以后,你们将被关进我刚才说的那个监狱,永远无法再交流。

#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 lastSeeLightOn[PriNum];    /*囚犯最后一次见到灯亮是自己第几次放风(第20顿饭之后)*/
    memset(seq,
0,sizeof(seq));
    memset(lastSeeLightOn,
-1,sizeof(lastSeeLightOn));
    
    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<<' ';
            }

            seq[anyone]
++;            /*该囚犯放风次数加1*/
            
if(light)                
                lastSeeLightOn[anyone]
=seq[anyone];        /*记住自己最后见到灯亮是第几次放风*/
            
if(seq[anyone]>GuessNum && light == 0 )        /*有人放风超过GuessNum次了*/    
            
{
            
//    if( lastSeeLightOn[anyone]< GuessNum/2 )    /*最后连续至少GuessNum/2次看到灯灭了*/
                {
                    
/*到现在,灯是灭的,只可能
                    ①PriNum 个囚犯都看过了;
                    ② 还有 2 个囚犯 一次都没出来过; 
                     当GuessNum足够时,万一的情况也就是还有1个倒霉鬼没出来过,但是
                    基于灯灭的情况,还剩2个倒霉鬼是几乎不可能存在的----这跟GuessNum的
                    取值有些关系,当GuessNum合适时,我们可以认为现在属于情况①:都放过风了,
                    所以,我们出狱吧-------如果确实出现了②的情况,我们也认了,好过于坐到老死@@
*/

                    proveOne
=anyone;
                    cout
<<"OK,let's go! ----our every times is: ";
                    
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]<<" ";
    }

    cout
<<" The 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;
}


      只要商量好GuessNum的值,就能一起释放,但也有极极极极极的可能会被砍头,但要不这样的话,就只有一起把牢底坐穿@-@
      >>>>费恁大力气就想出这么个破法子,不能100%保证一定可以出狱,汗,请其他室友共商良策_V_


评论列表
lcxzhwn
re: 看到一道有趣的题
呵呵!
生活之中真是处处皆学问啊!
lcxzhwn
re: 看到一道有趣的题
呵呵!
生活之中真是处处皆学问啊!
j
re: 看到一道有趣的题
1

发表评论
切换编辑模式