C++面试进阶之咖啡罐问题

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/suoyue_py/article/details/96889619

【题目描述】:
给定一个成有一些黑色豆子和一些白色豆子的咖啡罐以及一大堆“额外”的黑色豆子。重复下述过程,直至罐中只剩一颗豆子为止:
(1)从罐子中每次随机选取两颗豆子;
(2)若颜色相同,就将它们都扔掉并放入一个额外的黑色豆子;
(3)若颜色不同,就将白色豆子放回罐子中,而将黑色的豆子扔掉。
请设计程序模拟该过程,证明该过程会终止,从得出的结果推断出最后剩下豆子的颜色与最初白色豆子和黑色豆子的数量有什么数学关系?

【分析】:
题目抽象,有两个要求,第一个是设计程序模拟题目描述的过程,第二个是分析程序结果与咖啡豆数量之间的关系。
题目并没有说明咖啡罐中有多少粒咖啡豆及咖啡颜色的比例,故这是程序执行中需要输入的变量。
题目存在如下规则:
1)若摸出的咖啡豆同色,则放入一个黑咖啡豆;
2)若摸出的咖啡豆异色,则放入一个白色的咖啡豆;
由此条件可联想到离散数学的异或操作(XOR):
相同的两个数,异或结果为 0;
相异的两个数,异或结果为 1 。
由于咖啡豆颜色相异时放回白咖啡豆,故可用 0 代表黑咖啡豆,用 1 代表白咖啡豆。为满足咖啡豆的放入和丢弃操作,可选用链表来执行添加和操作的数据结构来存储咖啡豆。
最后一个咖啡豆与初始咖啡豆数量之间的关系:
设咖啡罐中共有 N 粒咖啡豆,其中黑色咖啡豆有 b 粒,白豆咖啡豆有 w 粒。每次取豆后咖啡罐中的豆数量都会减一,即 N 减一。每次取出两颗豆子总量都会减少1,则最后罐子中只剩一个,该过程一定会终结。
每次取的咖啡豆颜色有如下 3 种情况:
@两粒咖啡豆都是黑色(bb),把 2 个都扔掉,再放回 1 个额外的黑色豆子,
故此时黑色咖啡豆表示为: b-2 +1=b-1;
@两粒咖啡豆都是白色(ww),把 2 个都扔掉,再放回 1 个额外的黑色豆子,
故此时白色咖啡豆表示为: w-2 ;
@两粒咖啡豆颜色不同(bw),丢黑留白,即黑色咖啡豆减 1,白色咖啡豆数量不变。

由此可知,白色咖啡豆的数量要么不变化,要么两个两个的减少。
由此得出,若一开始咖啡罐里白色咖啡豆的数目为偶数,则剩下的一粒咖啡豆必然是黑色;若白色咖啡豆的数量为奇数,则剩下的一粒咖啡豆必然是白色。
由此看出,该题是利用“随机取出”字眼设置了一个陷阱,最后结果是固定的,与随机取出无关,只与咖啡豆的初始数量的奇偶性有关。

编译环境:
使用DEV C++来编译时,程序正常,不报错,但使用Visual C++来编译时程序会报如下错误:
在这里插入图片描述
这只是对 i 变量的定义问题,代码如下的 i 定义在DEVC++是允许的,使用 i 时就在内部定义,此处的 i 是同一个变量;
在这里插入图片描述
但在Visual C++中不允许同一变量的重复定义,故应将第二个for()循环里的 i 变量的定义去掉:
在这里插入图片描述
其实最好的解决方法应该是将变量 i 的定义放在for() 循环外,统一定义,而不是多次定义==》
在这里插入图片描述
运行结果:
在这里插入图片描述
代码:

#include <iostream>
#include <vector>
#include <time.h>
#include <stdlib.h>
using namespace std;

//定义咖啡罐类 
class CoffeeJar{			
public:
	CoffeeJar(int blackNum, int whiteNum){     //构造函数,初始化变量
		blackNumber = blackNum;
		whiteNumber = whiteNum;
		total = blackNumber+whiteNumber;
		int i;
		for (i = 0;i<blackNumber;i++){
			jar.push_back(0);
		}
		for (i = 0;i<whiteNumber;i++){
			jar.push_back(1);
		}
	}
	~CoffeeJar(){
		jar.clear();
		delete &jar;                   //析构函数,回收vector的空间
	}
	void getCoffeeBean();   		 //随机抽取豆子的方法
	bool isWhiteBean(int color){	//判断豆子的颜色是否为白咖啡豆
		return color == 1;
	}
	int getTotal(){			//获取咖啡豆的总数 
		return total;
	}
	void printBeanColor();			//打印咖啡豆颜色 
private:
	vector<int> jar;               //存储咖啡豆,0表示黑色,1表示白色
	int blackNumber;               //黑色咖啡豆数目
	int whiteNumber;               //白色咖啡豆数目
	int total;                     //咖啡豆的总数目
};

//随机抽取咖啡豆 
void CoffeeJar::getCoffeeBean(){
	int fBean = 0;  	 //初始化取的第一个豆子的颜色
	int sBean = 0;   	//初始化取的第二个豆子的颜色
	srand(static_cast<unsigned>(time(0)));           //设置随机数种子
	int maxRand = total;                             //设置随机数范围,即最大值
	int fIndex = rand()%maxRand;                     //随机抽取的第一粒豆子的下标	
	int sIndex = rand()%maxRand;                     //第二粒豆子的下标	
	if (fIndex != sIndex){                            //两次抽取的豆子不能使同一个	
		fBean = jar[fIndex];                         //设置第一粒咖啡豆的颜色
		sBean = jar[sIndex];                         //设置第二粒咖啡豆的颜色
		if(fBean == sBean){				//如果两粒咖啡豆的颜色相同	
			vector<int>::iterator iter = jar.begin()+fIndex;
			jar.erase(iter);                        //删除一粒咖啡豆
			if (jar.size() != 1) { 			//如果第二粒咖啡豆的存储位置在第一粒之后,索引减少一个 
				if(sIndex!=0 && sIndex > fIndex) { 
					sIndex--; 
				} 
				iter = jar.begin()+sIndex;			//移除咖啡豆 
				jar.erase(iter);
				jar.push_back(0); 					//添加一个黑色豆子 
			} else { 
				jar[0] = 0; 		//如果罐子中只剩一粒咖啡豆则直接添加黑色豆子 
			} 
		}else{					//如果两次取的豆子颜色不同则删除黑色豆子 
			if (!isWhiteBean(jar[fIndex])){     //判断豆子颜色
				vector<int>::iterator iter = jar.begin()+fIndex;
				jar.erase(iter);
			}else if (!isWhiteBean(jar[sIndex])){
				vector<int>::iterator iter = jar.begin()+sIndex;
				jar.erase(iter);
			}			
		}
		total = jar.size();             //更新咖啡罐中的咖啡豆总数
	}

}

//打印咖啡罐中的咖啡豆颜色 
void CoffeeJar::printBeanColor(){
	for (vector<int>::iterator i=jar.begin();i!=jar.end();++i){
		cout<<(*i)<<endl;
	}
}

//主函数 
int main(){
	int blackBeans,whiteBeans;             //黑色咖啡豆和白色咖啡豆的数目
	cout<<"请输入黑色咖啡豆和白色咖啡豆的数目:"<<endl;
	cin>>blackBeans>>whiteBeans;
	CoffeeJar *j = new CoffeeJar(blackBeans,whiteBeans);       //初始化咖啡罐
	while (j->getTotal()>1){
		j->getCoffeeBean();
	}
	cout<<"最后剩余的咖啡豆颜色为:"<<endl;
	j->printBeanColor();                       //打印最终剩余的咖啡豆的颜色
	return 0;
}

猜你喜欢

转载自blog.csdn.net/suoyue_py/article/details/96889619
今日推荐