通过非齐次线性方程组优化百鸡问题


引言:

  • 此算法为作者突发奇想而写,虽说是算法,但是实际上需要计算机来执行的部分并不多,更多的是通过人脑用数学方法来优化问题,将优化过的问题通过计算机的高性能实现穷举。

  • (萌新第一次写博客,不喜轻喷QAQ)


原题:
鸡翁一值钱五,鸡母一值钱三,鸡雏三值钱一。百钱买百鸡,问鸡翁、鸡母、鸡雏各几何?

译文:
一只公鸡值五钱,一只母鸡值三钱,三只小鸡值一钱。用一百钱买一百只鸡,求公鸡、母鸡、小鸡各几只。


一、思路

  1. 思想:通过数学方法简化问题(方程),将简化后的方程交由计算机进行处理。
  2. 主要操作:在原问题中提取出非齐次线性方程组,后用矩阵运算求其通解,最后使用程序遍历通解、得到结果。

二、具体操作

1、数学运算部分:

(1)、提取题目条件

  • ​ 公鸡的总价+母鸡的总价+小鸡的总价=100元

  • ​ 公鸡只数+母鸡只数+小鸡只数=100只

  • ​ 隐含条件:只数只能为非负整数。


设公鸡只数为 x x x,母鸡只数为 y y y,小鸡只数为 z z z,则可得方程组:
{ 5 x + 3 y + 1 / 3 z = 100 x + y + z = 100 \begin{cases} 5x+3y+1/3z=100\\ x+y+z=100 \end{cases} {5x+3y+1/3z=100x+y+z=100
为方便后续处理,易得:
{ 15 x + 9 y + z = 300 x + y + z = 100 \begin{cases} 15x+9y+z=300\\ x+y+z=100 \end{cases} {15x+9y+z=300x+y+z=100

(2)、线性代数运算

​ 已知方程组:
{ 15 x + 9 y + z = 300 x + y + z = 100 \begin{cases} 15x+9y+z=300\\ x+y+z=100 \end{cases} {15x+9y+z=300x+y+z=100
​ 设其增广矩阵为:
( A ∣ b ) = ( 15 9 1 300 1 1 1 100 ) (A|b)= \left( \begin{array}{ccc|c} 15&9&1&300\\ 1&1&1&100 \end{array} \right) (Ab)=(1519111300100)
​ 对增广矩阵矩阵进行初等行变换可得:
( A ∣ b ) → ( 1 1 1 100 0 − 6 − 14 − 1200 ) (A|b)→ \left( \begin{array}{ccc|c} 1&1&1&100\\ 0&-6&-14&-1200 \end{array} \right) (Ab)(10161141001200)
​ 易得系数矩阵的秩 r = 2 r=2 r=2 。设自由变量 z = 3 k z = 3k z=3k ,带入可得:
{ x + y + 3 k = 100 − 6 y − 14 ∗ 3 k = − 1200 \begin{cases} x+y+3k=100\\ -6y-14*3k=-1200 \end{cases} {x+y+3k=1006y143k=1200

​ 则非齐次线性方程组的通解为:
{ x = − 100 + 4 k y = 200 − 7 k z = 3 k \begin{cases} x=-100+4k\\ y=200-7k\\ z=3k \end{cases} x=100+4ky=2007kz=3k
​ 已知 x x x , y y y , z z z 均为非负整数,则 k k k 只可取整数。

2、程序部分(Python)

'''计数器初始化'''
k=0

'''判断x,y,z是否为非负整数的函数'''
def Int(num):
    if int(num) == num and int(num) >= 0:
        return True
    else:
        return False

'''主函数'''
'''当3*k,既z的数值大于100时,循环退出'''
while 3*k <= 100:

    '''遍历非齐次线性方程组的通解'''
    x = 100 * (-1) + k * 4
    y = 100 * 2 + k * (-7)
    z = 100 * 0 + k * 3

    '''判断三个个数是否同为非负整数,当同为非负整数时打印当前x,y,z值'''
    if Int(x) and Int(y) and Int(z):
        print(x,y,z)
        
    '''通解计数器递增'''
    k += 1

运行结果:

0 25 75
4 18 78
8 11 81
12 4 84

程序部分Q&A:

​ Q1.k可以为负值吗?

​ A:在方程组通解中, k k k 可以为负值,但在该函数中不可,方程组关于元素 z z z 的通解为 z = 3 k z=3k z=3k z z z 为非负整数,所以 k k k 只可取非负整数.

​ Q2. 循环退出条件可以用 x x x y y y 来表示吗?

​ A:可以,但需要改动。 x x x 可以直接用 x < = 100 x<=100 x<=100 ,但y需要表示为 y > = 0 y>=0 y>=0 ,究其原因,由通解易得 x ( k ) x(k) x(k) 为递增函数,而 y ( k ) y(k) y(k) 为递减函数。

三、算法分析

1、空间复杂度

​ 该算法在运行过程中没有创建临时变量,固空间复杂度为 O ( 1 ) O(1) O(1)

2、时间复杂度

​ 算法中只含有单层k次循环语句,固: 最佳时间复杂度 = 最差时间复杂度 = 平均时间复杂度 = O ( n ) {最佳时间复杂度}={最差时间复杂度}={平均时间复杂度}=O(n) 最佳时间复杂度=最差时间复杂度=平均时间复杂度=O(n)

​ 相较于暴力穷举法的时间复杂度为 O ( n 3 ) O(n^{3}) O(n3) ,该算法能显著降低时间复杂度。

四、问题分析

1、人脑vs电脑

​ 该算法的思路为通过人脑来优化问题,减小对机器性能的压力。在小型问题求解中,程序并不会对机器性能带来过大的压力,相反会通过人脑进行大量的运算,所以并非优解。但在大型问题的求解中(如万钱买万鸡,n钱买n鸡以及类似问题),该算法 O ( n ) O(n) O(n) ,相较于 O ( n 3 ) O(n^{3}) O(n3) 可大量减少对机器性能的压力。故该程序更适合大型问题的求解。

2、可读性

​ 该算法代码部分简介、一目了然,但是方程组部分难以理解,需要数学语言描述。但碍于大部分IDE不支持数学语言的注释,为提高可读性,需要在程序外额外添加数学语言注释(如上文 数学运算部分)。

  • 20
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值