算法笔记——15个瓶子,4只老鼠,测试哪瓶有毒

看到今天一道算法题,就写了一下自己的思路,希望有大牛,看到这个题,能提出更好的想法,再进行交流学习,我只用了一点简单的C++ 进行实现

有15个瓶子,其中最多有一瓶有毒,现在有四只老鼠,喝了有毒的水之后,第二天就会死。如何在第二天就可以判断出哪个瓶子有毒

我的想法是,因为最多有一瓶有毒,所以只有,0瓶有毒,或者其中一瓶有毒,所以是16种状态,所以用4只老鼠的喝下水的存活状态标级 '0' 或者 '1',来进行标记对应的瓶子

        0000 => 无毒
        0001 => 1号瓶
        0010 => 2号瓶
        0011 => 3号瓶
        0100 => 4号瓶
        0101 => 5号瓶
        0110 => 6号瓶
        0111 => 7号瓶
        1000 => 8号瓶
        1001 => 9号瓶
        1010 => 10号瓶
        1011 => 11号瓶
        1100 => 12号瓶
        1101 => 13号瓶
        1110 => 14号瓶
        1111 => 15号瓶

将水喂给当前瓶子编号每一位为 '1' 的老鼠,例如第7号瓶子,则给第二只,第三只,第四只老鼠喂瓶子里面的水,最后观察老鼠的存活状态,来判断是哪一瓶,比如最后是 '1011' 则是11号瓶有毒。
 

实现的算法如下:、

#include <iostream>
using namespace std; 
 
int main(){
	const int MOU_NUM = 4;//老鼠数量
	int mouse[MOU_NUM] = {0};//老鼠状态,'0'为存活,'1'为死亡
	int drug = 0;//有毒瓶子号
	for (int i = 0; i < MOU_NUM; i++)
	{
		cin>>mouse[i];//输入老鼠喝水后的存活状态
	}
	for (int i = 0; i < MOU_NUM; i++)
	{
		drug |= (mouse[i] << (MOU_NUM - i - 1));//进行位运算
	}
	//判断是否有毒
	if (drug == 0)
	{
		cout<<"没有有毒的"<<endl;
	}
	else{
		cout<<"有毒的是第"<<drug<<"瓶";
		return 0;
	}
}

核心的代码是第二个for循环中进行位运算的语句。运算分析过程如下:

首先是<<左移位运算符。

mouse[i] << (MOU_NUM - i - 1)

上面代码的意思mouse[i]所对应的二进制数字进行左移MOU_NUM - i - 1位,移动之后将左边自动补零。例如1<<2变成100,实际上相当于4,也就是1*2^2,因此对于a<<b,相当于a*2^b,也就是将a扩大2^b倍。

所以第二个for循环实际上是将for与左移之后的mouse[i]进行或运算。具体的运算过程如下:

如果输入1011,则mouse[0]=1,,mouse[1]=0,mouse[2]=1,mouse[3]=1

i=0时,drug=0,0|=(mouse[0]<<(4-0-1))

相当于0|=(1<<3),也就是0|=1*2^3,即0|=1000,相当于000|=1000,故drug=1000

i=1时,drug=1000,1000|=(mouse[1]<<(4-1-1))

相当于1000|=(0<<2),也就是1000|=0*2^2,即1000|=0,相当于1000|=0000,故drug=1000

i=2时,drug=1000,1000|=(mouse[2]<<(4-2-1))

相当于1000|=(1<<1),也就是1000|=1*2^1,即100|=2,相当于1000|=0010,故drug=1010

i=3时,drug=1010,1010|=(mouse[3]<<(4-3-1))

相当于1010|=(1<<0),也就是1010|=1*2^0,即1010|=0001,相当于1010|=0001,故drug=1011

二进制的1011就是十进制的11。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吉大秦少游

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值