• 可怜的小猪&香农熵


    这是一道leetcode上面的题:https://leetcode-cn.com/problems/poor-pigs/

     开始看到真的一头雾水,看了很多题解。最后恍然大悟只要明白进制这题也就不难了。

    下面以示例1参考:从1000个桶bucket中找到其中一桶有毒的,问在规定的时间内最少需要几头猪?


    桶状态bucket有且只有两种:无毒1、有毒0。

    猪的状态state有且只有两种:存活1、死亡0。

    有 bucket0 <--> state0  &  bucket1 <--> state1

    ------做一次实验试出毒药,找出1000桶bucket的毒药至少需要多少只猪呢?-------

    H(X) = log21000 = 9.96  10头  

    这也是香农熵的公式。

    1000桶按二进制(0/1)编码。每头猪给喂当前当前进制位上为1的桶的所有液体,如猪1喂(1,3,5,7.....),猪2喂(2,3,6,7,10....)。

    假设第666桶bucket是有毒的。

    那么结果必然是只有(1,3,6,7,9)号猪是活的,(2,4,5,8,10)号猪死了。那么猪死了就把对应的二进制位置为1,二进制转换1010011010 --------- 666。所以666桶有毒。

    --------------那么可以做4次试验,找出1000桶bucket的毒药至少需要多少只猪呢?-------------

    1、依然是把1000个桶bucket按照5进制分组;此时只需要5bit的信息。

    2、每头猪给喂当前进制位上为1的桶的所有液体(0-15分钟),当前进制位上为2的桶的所有液体(15-30分钟),当前进制位上为3的桶的所有液体(30-45分钟),当前进制位上为4的桶的所有液体(45-60分钟)。

    3、那么一只猪有5种状态,15分钟死亡(state1),30分钟死亡(state2),45分钟死亡(state3),60分钟死亡(state4),最终存活(state0);

    H(X) = log51000 = 4.29  5头

    最好的情况,5进制转换 11111 ------- 781,第一次试验就知道了781只桶有毒。

    同样假设第666桶有毒,那么结果必然是(1号、3号、5号)猪1轮亡,2号猪3轮亡,4号猪经过四轮后存活。5进制转换10131 ------ 666 ,结果是666号桶有毒。

    理解了这个编码就变得非常简单了

    class Solution {
            public int poorPigs(int buckets, int minutesToDie, int minutesToTest) {
                int state = minutesToTest / minutesToDie + 1;
                return (int)Math.ceil(Math.log(buckets)/Math.log(state));
            }
        }

    这里试验次数+1,才是state的状态。最后一种状态可以在前面结果全部取反时,直接得到。

    方案是没问题的,至于为什么这样做是最优的。香农大佬早已经给出了答案,任何想逾越这个极限去解决问题的人最后都会被证明是徒劳的。

    公式简单,但其背后关于进制的转换以及所蕴含的信息论知识是值得思考的。

     

    参考:

    https://www.zhihu.com/question/60227816/answer/1274071217

    https://leetcode-cn.com/problems/poor-pigs/solution/xiao-song-man-bu-dai-ma-bu-zhong-yao-xue-poet/

    https://leetcode-cn.com/problems/poor-pigs/

  • 相关阅读:
    人月神话阅读笔记之一
    第一阶段冲刺站立会议报告——9
    第一阶段冲刺站立会议报告——8
    第一阶段冲刺站立会议报告——7
    第一阶段冲刺站立会议报告——6
    第一阶段冲刺站立会议报告——5
    第二阶段冲刺第一天
    寻找水王2
    构建之法阅读笔记05
    第十二周学习进度条
  • 原文地址:https://www.cnblogs.com/chenfx/p/15615369.html
Copyright © 2020-2023  润新知