有1000只水桶,其中有且只有一桶装的含有毒药,其余装的都是水。它们从外观看起来都一样。如果小猪喝了毒药,它会在15分钟内死去。

问题来了,如果需要你在一小时内,弄清楚哪只水桶含有毒药,你最少需要多少只猪?

回答这个问题,并为下列的进阶问题编写一个通用算法。

进阶:

假设有 n 只水桶,猪饮水中毒后会在 m 分钟内死亡,你需要多少猪(x)就能在 p 分钟内找出“有毒”水桶?n只水桶里有且仅有一只有毒的桶。

答案:

1public int poorPigs(int buckets, int minutesToDie, int minutesToTest) {
2    int pigs = 0;
3    while (Math.pow(minutesToTest / minutesToDie + 1, pigs) < buckets) {
4        pigs += 1;
5    }
6    return pigs;
7}

解析:

其实应该说是一道数学题,一只猪可以测试的次数为minutesToTest/minusToDie,要么第一次死,要么第二次死……,要么都不死,所以共有(minutesToTest/minusToDie)+1种情况。即每次测试一只小猪要喝这些数量的桶中的水,base=minutesToTest/minusToDie+1,则base^pignum刚好大于buckets数量时需要的小猪数量最少。比如minutesToTest是60,minusToDie是15,5个桶,那么只需要1只猪即可。每15分钟喝一个桶的,如果60分钟内都没死,那么肯定最后一个桶有毒。同理,当minutesToTest是60,minusToDie是15,25个桶,那么只需要2只猪即可。只需要把25个桶放置为5行5列,第一只猪每15分钟喝每行的5桶水(混合的),第二只猪每15分钟喝每列的5桶水,根据死在什么时间内即可推算出第几桶水有毒,如果都没死,肯定是第25桶水有毒。如果minutesToTest是60,minusToDie是15,125个桶,那么只需要3只猪即可……或者下面这种写法也行

1public int poorPigs(int buckets, int m, int p) {
2    int t = p / m + 1;
3    return (int) Math.ceil(Math.log(buckets) / Math.log(t));
4}