【蓝桥杯】 历届试题 分糖果(模拟)—— 酱懵静

历届试题 分糖果

问题描述:
有n个小朋友围坐成一圈。老师给每个小朋友随机发偶数个糖果,然后进行下面的游戏:
每个小朋友都把自己的糖果分一半给左手边的孩子。
一轮分糖后,拥有奇数颗糖的孩子由老师补给1个糖果,从而变成偶数。
反复进行这个游戏,直到所有小朋友的糖果数都相同为止。
你的任务是预测在已知的初始糖果情形下,老师一共需要补发多少个糖果。

输入格式
  程序首先读入一个整数N(2<N<100),表示小朋友的人数。
  接着是一行用空格分开的N个偶数(每个偶数不大于1000,不小于2)
输出格式
  要求程序输出一个整数,表示老师需要补发的糖果数。

样例输入:
3
2 2 4
样例输出:4



---分割线---



分析:
大多说人看到这道题的时候其实都感觉挺简单的(当然,确实不难),反正就是模拟这个分糖以及发糖的过程嘛,最后统计补发糖果的数量即可。但是,再模拟那个发糖的过程时,便出现了错误。

我第一次模拟先是建立了一个int型数组childs来存储每个小朋友所拥有的糖果数量,接着通过一个循环(初始值从最后一个开始),把当前的childs[ i ]赋值为childs[ i ] / 2并加上childs[ i-1 ] / 2,即:childs[ i ] = ( childs[ i ] + childs[ i-1 ] ) / 2,最后再为第一个小朋友单独写交换糖果的代码。

但事实是,无论 i 初始从1开始还是从最后开始,总会出错!因为小朋友们在交换时,其实是一个环形结构,因此无论从那里作为切入口进去,都将错误地把当前切入的这个小朋友的糖果数默认为childs[ i ] / 2 。而实际上,这个小朋友的糖果数量应该为childs[ i ] /2 + childs[ i-1] / 2 (或者为childs[ i ] /2 + childs[ i+1] / 2)。
并且仔细一点的同学应该发现了,在循环中,当你执行完了某次childs[ i ] = ( childs[ i ] + childs[ i-1 ] ) / 2 后,对于下一次而言,其实这时的 child[ i ]已经不再是初始的那个childs[ i ]了(当然,childs[ i-1 ]也不是了)。因为当你的代码用到了这样的一个循环的时候,说明你已经默认这个分糖果的游戏是按序轮次一个一个进行的,而实际上,这个发糖的过程是所有小朋友同时开始分、发、接受的!(当然,理解错误有一部分是题目表意不明的原因)。

解题步骤:
既然是同时发糖的,那么我们何不多用两个数组来维护这个发糖的过程呢?
最开始,我用一个数组childs[i]来存储初始情况下每个小朋友手上的糖果数
并建立两个数组cld1[i]和cld2[i]用以维护之后的游戏过程
接着进入一个while(1)循环中
第一次做一个循环把每个小朋友手上的糖果数量除以2,然后把这个结果放进cld1[i]中
即:for(i=0;i<N;i++) cld1[i]=childs[i]/2;
然后再做一个循环把每个小朋友手上的糖果数量错位存储进cld2[i]中
即:for(i=1;i<N;i++) cld2[i]=cld1[i-1];
对于第一个特殊的需要单独错位:cld2[0]=cld1[N-1];
接下来我们便可以更新每个小朋友手上的糖果数量了
即:for(i=0;i<N;i++) childs[i]=cld1[i]+cld2[i];
紧接着我们再用一个循环判断每个小朋友手上的糖果数量是否相等,相等则退出当前while循环并输出最后老师补发的糖果数;不相等则检测需要发糖的,并把每次发糖的情况都记录下来,最后再继续执行最外层while。

下面给出本题完整代码:


---分割线---


#include<iostream>
using namespace std;
int main()
{
	int N,i,childs[100],sum=0;
	int cld1[100],cld2[100];
	cin>>N;
	for(i=0;i<N;i++)
		cin>>childs[i];
	while(1)
	{
		//二分处理
		for(i=0;i<N;i++)
			cld1[i]=childs[i]/2;
		for(i=1;i<N;i++)
			cld2[i]=cld1[i-1];
		cld2[0]=cld1[N-1];

		//合同处理
		for(i=0;i<N;i++)
			childs[i]=cld1[i]+cld2[i];
		int flag=childs[0];
		for(i=1;i<N;i++)
			if(childs[i]!=flag)
				break;

		//再次发糖
		if(i!=N)
		{
			for(i=0;i<N;i++)
				if(childs[i]%2!=0)	//检测到需要发糖
				{
					childs[i]++;
					sum++;
				}
		}
		
		//退出
		else break;
	}
	cout<<sum<<endl;
	return 0;
}


发布了30 篇原创文章 · 获赞 67 · 访问量 3056

猜你喜欢

转载自blog.csdn.net/the_ZED/article/details/100113416