zoukankan      html  css  js  c++  java
  • 100个犯人与灯泡

    有 100 个囚犯分别关在 100 间牢房里。牢房外有一个空荡荡的房间,房间里有一个由开关控制的灯泡。初始时,灯是关着的(或者随机)。看守每天随便选择一名囚犯进入房间,但保证每个囚犯都会被选中无穷多次。如果在某一时刻,有囚犯成功断定出所有人都进过这个房间了,所有囚犯都能释放。游戏开始前,所有囚犯可以聚在一起商量对策,但在此之后它们唯一可用来交流的工具就只有那个灯泡。他们应该设计一个怎样的协议呢?请根据此协议设计实现一个程序,把解题过程详细输出并给出解题所需天数。

    这个题目挺有意思的,建议自己先独立思考一下然后再看下面的解答

    Hint

    相当于每个人都只有一个小球,那个房间是一个只能放下一个小球的盒子,每个人将自己的小球放入盒子,计数者负责把每个小球收走并计数,如果收到小球的数量达到了99个,就说明每个人都进入过了这个房间

    代码实现

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 int counter, cnt;
     5 bool vis[100];
     6 bool flag;
     7 void put(int id) {
     8     if (counter == -1) {
     9         counter = id; // 第一个进入房间的人当计数者
    10         flag = 0; // 将灯恢复关闭状态
    11         return;
    12     }
    13     if (id == counter && flag) {
    14         // 只有计数者将灯关闭并计数
    15         flag = 0;
    16         ++cnt;
    17     }
    18     if(id != counter && !flag && !vis[id]) {
    19         // 非计数者第一次见到灯灭时,将灯打开
    20         vis[id] = 1;
    21         flag = 1;
    22     }
    23 }
    24 
    25 bool check() {
    26     // 检查是否所有人都进入了房间
    27     return cnt == 99;
    28 }
    29 
    30 int main() {
    31     srand(time(NULL));
    32     flag = rand() % 2; // 初始灯的状态随机
    33     counter = -1;
    34     while (true)
    35     {
    36         int id = rand() % 100; // 每次随机一个人进入房间
    37         put(id);
    38         if (check()) 
    39             break;
    40     }
    41     return 0;
    42 }

    如果假设不知道进入房间的人不知道是第几天,则可以随便指定一个人作为计数者,然后其他每个人都有两个小球(即两次机会将灯打开),那么计数者最多收到的小球个数要么是198个小球或者199个小球,那么也就是说,当计数达到了198就可以认定为每个人都至少一次到过了这个房间,就避免了初始状态未知不定带来的干扰

    参考资料
    100 Prisoners and A light Bulb
    100个囚犯和灯泡的那些事儿 - Matrix67

  • 相关阅读:
    Linux权限
    Linux用户和用户组操作
    input输入框美化
    Ajax原理一篇就够了
    CSS样式----浮动(图文详解)
    linx系统操作
    文件打包,压缩,解包,解压缩
    Linux学习笔记(一)
    ios 11导航栏替换返回按钮图片,隐藏文字
    swift开发笔记23 BirthDays
  • 原文地址:https://www.cnblogs.com/ZKin/p/9594170.html
Copyright © 2011-2022 走看看