标题:分糖果
有n个小朋友围坐成一圈。老师给每个小朋友随机发偶数个糖果,然后进行下面的游戏:
每个小朋友都把自己的糖果分一半给左手边的孩子。一轮分糖后,拥有奇数颗糖的孩子由老师补给1个糖果,从而变成偶数。反复进行这个游戏,直到所有小朋友的糖果数都相同为止。 你的任务是预测在已知的初始糖果情形下,老师一共需要补发多少个糖果。
【格式要求】
程序首先读入一个整数N(2<N<100),表示小朋友的人数。
接着是一行用空格分开的N个偶数(每个偶数不大于1000,不小于2)
要求程序输出一个整数,表示老师需要补发的糖果数。
例如:输入
3
2 2 4
程序应该输出:
4
资源约定:
峯值内存消耗 < 256M
CPU消耗 < 1000ms
分析:本题其实没有多少难度,就是用一个模拟法,把每次分糖果,发糖果的过程模拟出来,知道最后每个人手里糖果数一样即可
#include<iostream>
using namespace std;
#define Max 100
int a[Max];
int N;
int main()
{
cin>>N;
bool isGoON=false;
for(int i=0;i<N;i++)
{
cin>>a[i];
if(i!=0)
if(a[i]!=a[i-1])
isGoON=true;
}
int res=0;
while(isGoON)
{
int last=a[0];
for(int i=0;i<N;i++) //last记录上一次循环时,记录的下次的值,也就是原本a[i]
{
int next=(i+1)%N;
a[i]-=last/2; //这里不能写成a[i]=last/2;虽然last是保存原本a[i]的值,但是这里的a[i]已经不是原本的a[i]
int temp=a[next]; //因为在上一次的循环中进行的a[next]+=last/2;操作,使得这里的a[i]是原先的a[i]加上a[i-1]分配的糖果
a[next]+=last/2;
last=temp; //将下一个的值记录下来,
}
isGoON=false;
for(int i=0;i<N;i++)
{
if(a[i]%2!=0)
{
a[i]++;
res++;
}
if(i!=0 && a[i]!=a[i-1])
if(a[i]!=a[i-1])
isGoON=true;
}
}
cout<<res<<endl;
return 0;
}
这里上述源代码中,每次孩子发糖果时,最终手里糖果数为现自己手里糖果数一半加上一个人手里糖果数一半,这里当遍历到下一个孩子时,取得上一个孩子手里的糖果数,因为此时上一个孩子手里糖果数是最终分好的,所以想获得原来他手里一半的糖果时,就需要个变量保存其原本手里的糖果数,这里我使用的是last变量.
上述的方法虽然代码简单,但是有很多注意的小点,当时我写的时候也是调试了一会,所以又想了另一简单易懂并且便于代码的方法:
#include<iostream>
using namespace std;
#define Max 100
int a[Max];
int fen[Max];
int N;
int main()
{
cin>>N;
bool isGoON=false;
for(int i=0;i<N;i++)
{
cin>>a[i];
if(i!=0)
if(a[i]!=a[i-1])
isGoON=true;
}
int res=0;
while(isGoON)
{
for(int i=0;i<N;i++)
{
fen[i]=a[i]/2;
}
isGoON=false;
for(int i=0;i<N;i++)
{
int last=(i-1+N)%N;
a[i]+=fen[last];
a[i]-=fen[i];
if(a[i]%2!=0)
{
a[i]++;
res++;
}
if(i!=0)
if(a[i]!=a[i-1])
isGoON=true;
}
}
cout<<res<<endl;
return 0;
}
上述的方法,将每个孩子分出来的糖果重新构成一个数组,即这里的fen[],那么最终孩子手里糖果数就等于“原本糖果数+上一个孩子分出来的糖果-自己分出去的糖果数”,也就是上述的公式 a[i]+=fen[last]; a[i]-=fen[i];
PS:没啥好说的,准备比赛就是要刷题~