“可怜的小猪”| “朝闻道”知识分享大赛

这是我参加“朝闻道”知识分享大赛第1篇文章

一、题目如下:

buckets 桶液体,其中 正好有一桶 含有毒药,其余装的都是水。它们从外观看起来都一样。为了弄清楚哪只水桶含有毒药,你可以喂一些猪喝,通过观察猪是否会死进行判断。不幸的是,你只有 minutesToTest 分钟时间来确定哪桶液体是有毒的。

喂猪的规则如下:

  1. 选择若干活猪进行喂养
  2. 可以允许小猪同时饮用任意数量的桶中的水,并且该过程不需要时间。
  3. 小猪喝完水后,必须有 minutesToDie 分钟的冷却时间。在这段时间里,你只能观察,而不允许继续喂猪。
  4. 过了 minutesToDie 分钟后,所有喝到毒药的猪都会死去,其他所有猪都会活下来。
  5. 重复这一过程,直到时间用完。

给你桶的数目 buckets ,minutesToDie 和 minutesToTest ,返回 在规定时间内判断哪个桶有毒所需的 最小 猪数 。

二、题解:

该题可用N进制来实现

   1. 我们先考虑一种简单的情况:buckets = 1000, minutesToDie = 15, minutesToTest = 15

那么此时时间只能喝一次,一次过后小猪要么死,要么活。

       我们把1000桶液体标上0-999的编号,由于2^10>1000>2^9,因此每桶液体都对应着一个长度为10的二进制串,所以我们需要10只小猪,每一只小猪管理一个二进制位,假如第一只小猪负责二进制最低位,让它喝掉所有最低位为1的液体,如果最后存活,则毒药编号二进制最低位为0,反之为1.通过此种方法我们可以得到毒药的所有二进制位,最终精准确定有毒液体的编号,找出有毒液体。

    2. 我们考虑更一般的情况: 

        buckets = 1000, minutesToDie = 15, minutesToTest = 60

        此时每只小猪可以喝4次液体,在时间限制范围内,小猪可能出现的状态共有5种,分别为:喝完第1次后死亡、喝完第2次后死亡、喝完第3次后死亡、喝完第4次后死亡、喝完4次后依然存活. 现在每只小猪可以表示5种状态了那么我们就可以将瓶子的编号转换成五进制数考虑。

        我们依然给这 1000 瓶液体分别标上一个唯一编号 0-999,由于 5^5>1000>5^4,所以每瓶液体都对应着唯一的一个长度为5的五进制串. 我们只需要5只小猪,让每个小猪负责一个五进制位即可. 例如第一只小猪负责五进制串的最低位,那么它第一次先喝掉五进制最低位为1的液体,第二次喝掉五进制最低位为2的液体,第三次喝掉五进制最低位为3的液体,第四次喝掉五进制最低位为4的液体. 在这一过程中,如果这只小猪某次喝完后死亡,就可以立马确定有毒液体五进制的最低位取值,如果喝完四次后仍存活,说明有毒液体五进制的最低位为0. 这样一来,一只小猪就可以确定一个五进制位的取值,使用5只小猪就能完全确定有毒液体的编号.

三、代码

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

      此题官方题解采用动态规划和数学来解,自己觉得有点难理解,在评论区看见了N进制解法,觉得容易理解一点,如有错误请指正

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值