问题描述
10个小孩围成一圈分糖果:
老师分给第1个小孩10块,
- 第2个小孩2块,
- 第3个小孩8块,
- 第4个小孩22块,
- 第5个小孩16块,
- 第6个小孩4块,
- 第7个小孩10块,
- 第8个小孩6块,
- 第9个小孩14块,
- 第10个小孩20块。
然后所有的小孩同时将手中的糖分一半给右边的小孩;糖块数为奇数的人可向老师要一块。问经过这样几次后大家手中的糖一样多?每人各有多少块糖?
问题分析
根据题意,10个小孩开始时所拥有的糖果数是不同的,但分糖的动作却是相同的,即“所有的小孩同时将手中的糖分一半给右边的小孩;糖块数为奇数的人可向老师要一块”。因此,这是一个典型的可使用循环结构来解决的问题。
将老师开始给每个小孩分配的糖果数作为循环的初始条件,以“所有的小孩同时将手中的糖分一半给右边的小孩;糖块数为奇数的人可向老师要一块”这个重复的动作作为循环体,循环的结束条件为所有小孩手中的糖块数一样多。在循环体中,还需要判断糖块数的奇偶性,奇偶性不同完成的操作也不相同,显然这需要使用一个选择结构来实现。
算法设计
在问题分析中,我们已经确定了该问题使用循环结构来解决。那么如何存放每个小孩初始时所拥有的糖果数呢?这里考虑使用数组来存放老师开始给每个小孩分配的糖果数,因为有10个小孩,故定义一个长度为10的整型数组即可。在循环过程中,糖果每经过一次重新分配,就打印输出一次,直到最后一次打印时,10个小孩所拥有的糖果数都相同,此时结束循环。
确定程序框架
- 定义整型数组存放初始条件
# sweet[0]=10表示第一个小孩的糖果数为10,以此类推
sweet = [10, 2, 8, 22, 16, 4, 10, 6, 14, 20]
将老师开始给每个小孩分配的糖果数存放到sweet数组中。
- 循环结构实现框架
while (10个孩子手中的糖果数不相同): # 若不满足要求则继续循环
# 将每个孩子手中的糖果数平分为两份
for i in range(0, 10):
if sweet[i] % 2 == 0: # 若为偶数则直接分出一半
sweet[i] = sweet[i] // 2
t[i] = sweet[i]
else: # 若为奇数则加1后再分出一半
sweet[i] = (sweet[i] + 1) // 2
t[i] = sweet[i]
# 将分出的一半糖果给右边的孩子
for n in range(0, 9):
sweet[n + 1] = sweet[n + 1] + t[n]
sweet[0] += t[9]
j += 1
printResult(sweet, j) #输出当前每个孩子手中的糖果数
上面的代码在while循环结构中又包含了两个for循环。while循环的循环条件为“10个孩子手中的糖果数不相同”,第一个for循环用来将当前每个孩子手中的糖果分成一半,同时将分配结果保存在数组t中。在分配时注意区分奇偶数糖果分配方式的不同。第二个for循环用来将每个孩子手中已分好的一半的糖果给右边的孩子,由于第一个for循环中已经将每个孩子手中一半的糖果数保存在t数组中了,因此可直接利用t数组中的值修改sweet数组中的对应元素值。又由于“10个小孩围成一圈分糖果”,因此,sweet[9]右边的元素为sweet[0]。
- 定义judge()函数
judge()函数用来判断每个孩子手中的糖果数是否相同。judge()函数的参数为整型数组,它可以判断该数组中各个元素的值是否相同,如果数组中所有元素的值都相同,则judge()函数返回值为0,否则judge()函数返回值为1。
judge()函数代码如下:
# 判断每个孩子手中的糖果数是否相同
def judge(candy):
for i in range(0,10):
if candy[0] != candy[i]:
return 1 # 不相同返回1
return 0 #相同返回0
完整的程序
根据上面的分析,编写程序如下:
# 函数:判断列表中各成员是否相等
# candy:保存糖果数量的列表
def judge(candy):
for i in range(0, 10):
if candy[0] != candy[i]:
return 1 # 不相同返回1
return 0 # 相同返回0
# 输出列表中每个元素的值
# s: 要打印的列表
# j: 需要打印的次数计数器
def print_result(s, j):
print("%4d" % j, end=" ")
for k in range(10): # 打印列表
print("%4d" % s[k], end=" ")
print() # 换行
# 分糖的函数
# sweet: 保存糖果数量的列表
# j: 计数器,记录分糖的次数
def giveSweets(sweet, j):
t = [0] * 10 # 临时表,保存每次分出去的一半糖
while (judge(sweet)): # 若不满足要求则继续循环
# 将每个孩子手中的糖果数平分为两份,放到t列表中
for i in range(0, 10):
if sweet[i] % 2 == 0: # 若为偶数则直接分出一半
sweet[i] = sweet[i] // 2
t[i] = sweet[i]
else: # 若为奇数则加1后再分出一半
sweet[i] = (sweet[i] + 1) // 2
t[i] = sweet[i]
# 将分出的一半糖果t[n] 给右边的孩子 sweet[n + 1]
for n in range(0, 9):
sweet[n + 1] = sweet[n + 1] + t[n]
sweet[0] += t[9] # 第10个分出去的一个t[9],给第一个孩子:sweet[0]
j += 1 # 计数器加1
print_result(sweet, j) # 打印本次分糖后的结果
# 定义列表sweet,存储老师给每个孩子分配的糖果数
# sweet[0]=10表示第一个小孩的糖果数为10,以此类推
sweet = [10, 2, 8, 22, 16, 4, 10, 6, 14, 20]
print("次数 各人糖果数")
j = 0 # 计数器,保存分糖的次数
# 输出每个孩子手中的糖果数
print("%4d" % j, end=" ")
for i in range(len(sweet)):
print("%4d" % sweet[i], end=" ")
print()
# 开始分糖
giveSweets(sweet, j) # 调用分糖果函数
运行结果
在vcode
下运行程序,结果如下图所示。从输出结果可知,经过17次分糖过程后,10个孩子手中的糖果数相等,都为18块。