有趣的老鼠找毒瓶算法


先看下題目:有15個瓶子,瓶子中都裝有水,但是其中有一個瓶子的水是有毒的,現(xiàn)在有4只老鼠,老鼠喝了有毒的水后會在第二天死亡,如何設計老鼠喝水可以再第二天通過觀察老鼠的狀態(tài)來判斷哪個瓶子的水有毒?

分析一下題目:每瓶水對于每只老鼠來說都有喝或者不喝兩種狀態(tài),4只老鼠對于每瓶水都可以有 0000 -> 1111 16中狀態(tài),由于要確認有毒,所以舍棄掉第一種都不喝的狀態(tài)(0000),剩余15中狀態(tài)正好與15個瓶子一一對應,所以我們可以取瓶子編號的后4位(0001->1111)來對應4只,老鼠是否喝這瓶水的狀態(tài) 0代表喝 1代表不喝,最后根據(jù)4只老鼠的中毒狀態(tài)來代表4個bits就可以得到哪個瓶子有毒了。

理清了思路,就可以用代碼驗證一下了:

先根據(jù)題目創(chuàng)建老鼠和瓶子的類


@interface BottleWater : NSObject
// 是否有毒
@property (nonatomic,assign) BOOL poisonous;
@property (nonatomic,assign) NSUInteger num; // 編號
@end
@implementation BottleWater
-(NSString *)description
{
    return [NSString stringWithFormat:@"%lu號瓶子,%@毒",_num,_poisonous?@"有":@"無"];
}
@end

@interface Mouse : NSObject
// 是否中毒
@property (nonatomic,readonly,assign) BOOL poisoning;
@property (nonatomic,assign) NSUInteger num;// 編號
@property (nonatomic,readonly,getter=nextDayStatus) BOOL isLiving;
@end
@implementation Mouse
@synthesize poisoning = _poisoning;

- (void)drinkWater:(BottleWater *)water
{
    if (water.poisonous) {
        _poisoning = YES;
    }
}
- (BOOL)nextDayStatus
{
    return !_poisoning;
}
-(NSString *)description
{
    return [NSString stringWithFormat:@"%lu號老鼠%@中毒",_num,_poisoning?@"":@"未"];
}
@end

然后根據(jù)思路設計代碼:
首先創(chuàng)建瓶子和老鼠

        // 創(chuàng)建瓶子
        NSMutableArray <BottleWater *>*waters = [NSMutableArray arrayWithCapacity:1];
        int poisoningNum = arc4random()%15+1;
        NSLog(@"第%d瓶有毒",poisoningNum);
        for (int i=1; i<=15; i++) {
            BottleWater *water = [[BottleWater alloc] init];
            water.num = i;
            if (i == poisoningNum) {
                water.poisonous = YES;
            }
            [waters addObject:water];
        }
        // 創(chuàng)建老鼠
        NSMutableArray <Mouse *>*mouses = [NSMutableArray arrayWithCapacity:1];
        for (int i=1; i<=4; i++) {
            Mouse *mouse = [[Mouse alloc] init];
            mouse.num = i;
            [mouses addObject:mouse];
        }

用瓶子的編碼的后4位的每一位分別代表每個老鼠是否喝此瓶水

        for (UInt8 i=1; i<=waters.count; i++) {
            UInt8 index1,index2,index3,index4;
            // 取位
            index1 = i & 1; // 第一個老鼠是否喝
            index2 = i & 2; // 第二個老鼠是否喝
            index3 = i & 4; // 第三個老鼠是否喝
            index4 = i & 8; // 第四個老鼠是否喝
            if (index1) {
                [mouses[0] drinkWater:waters[i-1]];
            }
            if (index2) {
                [mouses[1] drinkWater:waters[i-1]];
            }
            if (index3) {
                [mouses[2] drinkWater:waters[i-1]];
            }
            if (index4) {
                [mouses[3] drinkWater:waters[i-1]];
            }
        }

水已喝完,驗證一下是否找對有毒的瓶子

        // 假設一天后
        UInt8 number = 0; // 有毒的瓶子
        for (UInt i=0; i<mouses.count; i++) {
            NSLog(@"%@",mouses[i]);
            UInt8 j = mouses[i].isLiving ? 0 : 1 << i;
            number |= j;
        }
        NSLog(@"-------------------");
        NSLog(@"有毒的瓶子編號是:%d",number);

打印如下

2018-11-22 17:08:42.042593+0800 Demo[1686:108521] 第10瓶有毒
2018-11-22 17:08:42.042883+0800 Demo[1686:108521] 1號老鼠未中毒
2018-11-22 17:08:42.042937+0800 Demo[1686:108521] 2號老鼠中毒
2018-11-22 17:08:42.042961+0800 Demo[1686:108521] 3號老鼠未中毒
2018-11-22 17:08:42.042974+0800 Demo[1686:108521] 4號老鼠中毒
2018-11-22 17:08:42.042983+0800 Demo[1686:108521] -------------------
2018-11-22 17:08:42.042999+0800 Demo[1686:108521] 有毒的瓶子編號是:10

Demo

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容