一、问题
碰到一个比较好玩的问题,我有许多小额的发票,需要从这些发票中凑出一个指定的整数来。怎么去实现呢?
二、规划求解
在excel中,有一个功能是“规划求解”,具体可以参看链接:规划求解。
规划求解怎么算的,我也不知道,我们来看看用python怎么实现。
三、python实现
这些小额发票,我们可以用一个列表来表示。比如a = [1, 3, 5, 6, 8]。
那么这个列表的元素可能产生多少种组合呢?
由于列表里面每一个元素都可能有,也可能没有。
所以这里面就有2的5次方种变化。
似乎我只需要对上面的二维数组里面每一个元素,即一维数组求和即可。列表中有5个数,有32种可能性,这么操作可行。但是,假如是10个数则有1024(2的10次方)种可能性,20个数就有1048576(2的20次方)种可能性,30个数则有1073741824(2的30次方)种可能性。组合的可能性可是指数翻番,电脑根本存不下这么长的列表。那就得再想其它办法。
现在的问题是,在没有这个长列表的情况下,我怎么去遍历这些所有组合呢。我们用多层嵌套的方式求解。
这样我们就不用存这个长列表,只要把每一个data跟设定的总数进行对比即可。但是问题又来了,如果给了我30张发票,我要写30个嵌套循环吗?那画面简直无法想象。
我们注意到,列表里面每个元素,只有两种状态,即有和没有。那么可以再创建一个列表,表示状态,0表示没有,1表示有。即
这样就只需要更改coefficient里面每个元素的状态即可。为了实现coefficient这个列表各种可能性,我们可以采用把数字转为二进制,然后将二进制数每个数字位分开的方式。
代码如下。
结果如下:
这样就只需要把列表a和列表coefficient的每个元素相乘累加即可。
四、代码
最后呈现的代码如下,我有29张发票,要求得到的值是180。
以下是结果:
五、总结
介绍了如何将多层嵌套转化为一维数组进行运算
本文采用暴力破解,耗时较久。抛砖引玉,欢迎大家留言,提供节省时间复杂度的算法。