题目是这样的,一包重物40千克,被摔成了4份,刚好这四份重物可以称出1,40千克任意重量的物品,求这四份的重量。
首先还是先理解一下题目,什么叫称出零到四十千克的物品?
打比方说,1,2,5三种重物,可以称出1,2,5,3,6,7,8,4等等,其实就是三种重物任意加减得到的值(减法意味放在天秤的另一端),那么这种题怎么做呢?其实抽象一下可以得到一个方程
X*Y=Z
其中X是一个矩阵,代表加减或者不取的操作,Y是一个矩阵代表4个重物的重量,Z代表可以得到的所有重量,再举一个例子,两个重物分别为1,4,那么这个矩阵方程就是:
[(-1,-1),(-1,0),(-1,1),(0,-1),(0,0),(0,1),(1,-1),(1,0),(1,1)]*[(4,1)]=[(...)]
后面是能够表示的重量。
现在我们的问题是我们知道了X(对4个数的加减或不取操作,是个3^4*4的矩阵),知道了Z(由于考虑了减法,所以应该是-40到40,是个81*1的矩阵),求Y。
因为numpy有对矩阵很好的支持,所以就偷懒了(本来也不太会矩阵算法)
#!/usr/bin/env python
import numpy as np
x=[(i,j,k,l) for i in (-1,0,1) for j in (-1,0,1) for k in (-1,0,1) for l in (-1,0,1)]
z=';'.join([str(i) for i in xrange(-40,41)]) #这个是numpy转化矩阵时候必要的格式
X=np.matrix(x)
Z=np.matrix(z)
Y=X.I*Z #I表示逆矩阵,注意一定要左乘
print Y
输出:
[[ 27.]
[ 9.]
[ 3.]
[ 1.]]
其实看了上面的方法以后,可以很明显的发现根本需要这么庞大一个方程。因为未知数只有4个,所以只要一个四元一次方程组即可解,根据上面的意思,可以列出方程(这里所谓无用的方程是指与之前的方程系数组成的矩阵通过矩阵变换可以变成0的方程,对解未知数没有作用):
(suppose x>y>z>w)
x+y+z+w=40 -----a
x+y+z+0*w=39 -----b
(x+y+z-w=38无用)
x+y+0*z+w=37 -----c
(中间有5个无用的方程)
x+0*y+z+w=31 -----d
联立a,b,c,d可以解出答案(关键只要知道组成四十个数的运算从大到小怎么排的就可以了)