百钱买百鸡Python编程详解
中国古代数学家张丘建在他的《算经》中提出了一个著名的“百钱百鸡问题”:一只公鸡值五钱,一只母鸡值三钱,三只小鸡值一钱,现在要用百钱买百鸡,请问公鸡、母鸡、小鸡各多少只?
因公鸡的取值范围是 0~20,可用循环语句
针对本题来说,每层循环的初值是 0(即买的 100 只鸡中,可能没有公鸡,也可能没有母鸡或小鸡),循环的控制条件是公鸡、母鸡和小鸡用百钱最多能够买到的数量(公鸡最多 20 只,母鸡最多 33 只,小鸡最多 100 只,虽然百钱最多可以买到 300 只小鸡,但题目要求只买100只)。穷举循环的特点就是把所有情况都考虑到,因此每层循环执行一次,对应循环变量的值就要加1。
程序流程图如下图所示:
根据流程图,构建程序框架如下:
因此结果输出之前,我们要把合理的方案筛选出来,即如果结果满足 cock+hen+chicken=100 和 5×cock+3×hen+chicken/3=100,则输出。很明显,控制条件即为语句
对于本题来说,公鸡的数量确定后,小鸡的数量就固定为 100-cock-hen,无须再进行穷举了,此时约束条件只有一个,即 5×cock+3×hen+chicken/3=100,这样我们利用两重循环即可求解本题,代码如下:
问题分析
用百钱如果只买公鸡,最多可以买 20 只,但题目要求买 100 只,由此可知,所买公鸡的数量肯定在 0~20 之间。同理,母鸡的数量在 0~33 之间。在此不妨把公鸡、母鸡和小鸡的数量分别设为 cock、hen、chicken,则 cock+hen+chicken=100,因此百钱买百鸡问题就转化成解不定方程组的问题了。算法设计
对于不定方程组,我们可以利用穷举循环的方法来解决,也就是通过对未知数可变范围的穷举,验证方程在什么情况下成立,从而得到相应的解。因公鸡的取值范围是 0~20,可用循环语句
for cock in range(0,21)
实现。钱的数量是固定的,要买的鸡的数量也是固定的,所以母鸡数量是受到公鸡数量限制的。同理,小鸡数量受到公鸡和母鸡数量的限制,因此我们可以利用三层循环的嵌套来解决,第一层循环控制公鸡的数量,第二层控制母鸡的数量,最内层控制小鸡的数量。确定程序框架
在设计循环时首先要考虑循环的三要素,即循环变量的初值、循环的控制条件和使循环趋于结束的循环变量值的改变。针对本题来说,每层循环的初值是 0(即买的 100 只鸡中,可能没有公鸡,也可能没有母鸡或小鸡),循环的控制条件是公鸡、母鸡和小鸡用百钱最多能够买到的数量(公鸡最多 20 只,母鸡最多 33 只,小鸡最多 100 只,虽然百钱最多可以买到 300 只小鸡,但题目要求只买100只)。穷举循环的特点就是把所有情况都考虑到,因此每层循环执行一次,对应循环变量的值就要加1。
程序流程图如下图所示:
根据流程图,构建程序框架如下:
cock = 0 while cock <= 20: # 内层循环控制母鸡数量取值范围为0~33 hen = 0 while hen <= 33: #内层循环控制小鸡数量取值范围为0~100 chicken = 0 while chicken <= 100: #条件控制 print("cock=%2d,hen=%2d,chicken=%2d\n" %(cock,hen,chicken)) chicken += 1 hen += 1 cock += 1根据这三层循环,我们可以得到很多种方案,在这些方案中有些是不符合 cock+hen+chicken=100 并且 5×cock+3×hen+chicken/3=100 这两个条件的。
因此结果输出之前,我们要把合理的方案筛选出来,即如果结果满足 cock+hen+chicken=100 和 5×cock+3×hen+chicken/3=100,则输出。很明显,控制条件即为语句
if(5×cock+3×hen+chicken/3.0==100)and(cock+hen+chicken==100)
。
完整的程序
根据上面的分析,编写程序如下:if __name__=="__main__": # cock表示公鸡数量,hen表示母鸡数量,chicken表示小鸡数量,总共100只 # 外层循环控制公鸡数量取值范围为0~20 cock = 0 while cock <= 20: # 内层循环控制母鸡数量取值范围为0~33 hen = 0 while hen <= 33: #内层循环控制小鸡数量取值范围为0~100 chicken = 0 while chicken <= 100: # 条件控制 if (5 * cock + 3 * hen + chicken / 3.0 ==100) and (cock + hen + chicken ==100): print("cock=%2d,hen=%2d,chicken=%2d" %(cock,hen,chicken)) chicken += 1 hen += 1 cock += 1程序的运行结果为:
cock= 0,hen=25,chicken=75
cock= 4,hen=18,chicken=78
cock= 8,hen=11,chicken=81
cock=12,hen= 4,chicken=84
更高效的程序
以上算法需要穷举尝试 21×34×101=72114 次,算法的效率显然太低了。对于这类求解不定方程的问题,各层循环的控制变量直接与方程的未知数相关,并且采用对未知数的取值范围穷举和组合的方法得到全部的解。对于本题来说,公鸡的数量确定后,小鸡的数量就固定为 100-cock-hen,无须再进行穷举了,此时约束条件只有一个,即 5×cock+3×hen+chicken/3=100,这样我们利用两重循环即可求解本题,代码如下:
if __name__=="__main__": # 外层循环控制公鸡数量取整范围为0~20 cock = 0 while cock <= 20: # 内层循环控制母鸡数量取值范围为0~30 hen = 0 while hen <= 33: # 小鸡的数量 chicken = 100 - cock - hen if 5 * cock + 3 * hen + chicken / 3.0 == 100: print("cock=%2d,hen=%2d,chicken=%2d" %(cock, hen, chicken)) hen+=1 cock+=1程序的运行结果为:
cock= 0,hen=25,chicken=75
cock= 4,hen=18,chicken=78
cock= 8,hen=11,chicken=81
cock=12,hen= 4,chicken=84