有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}