Python 基于时间的优化算法

Python 基于时间的优化算法,python,algorithm,optimization,time-complexity,Python,Algorithm,Optimization,Time Complexity,我正在为这个问题编写一个算法,算法很简单,我已经编写了代码,但我看不到任何可能的优化: 我有一个装满100块石头的桶,还有5个孩子用它来装饰他们的沙堡。 每个孩子每隔一定的时间重复捡起一块石头,每个孩子都是独立的,更多的孩子可以同时捡起一块石头,总共有5个孩子: 埃里克每5分钟捡一块石头 马克每10分钟捡一块石头 劳拉每7分钟捡一块石头 艾玛每三分钟捡一块石头 弗兰克每三分钟捡一块石头 我们需要多少分钟来清空这个桶 更清楚的是:10分钟后,埃里克举起了两块石头(第5分钟和第10分钟),而艾玛

我正在为这个问题编写一个算法,算法很简单,我已经编写了代码,但我看不到任何可能的优化:

我有一个装满100块石头的桶,还有5个孩子用它来装饰他们的沙堡。 每个孩子每隔一定的时间重复捡起一块石头,每个孩子都是独立的,更多的孩子可以同时捡起一块石头,总共有5个孩子:

  • 埃里克每5分钟捡一块石头
  • 马克每10分钟捡一块石头
  • 劳拉每7分钟捡一块石头
  • 艾玛每三分钟捡一块石头
  • 弗兰克每三分钟捡一块石头
我们需要多少分钟来清空这个桶

更清楚的是:10分钟后,埃里克举起了两块石头(第5分钟和第10分钟),而艾玛举起了3块石头(第3分钟、第6分钟和第9分钟)

10分钟后,孩子们总共有2+1+1+3+3=10块石头,桶里有90块石头

这是我的代码(Python 3):

children\u rate=[3,3,5,7,10]
桶=100
分钟=0
尽管如此:
分钟+=1
对于儿童中的儿童,费率:
如果分钟数%child==0:
桶-=1
如果bucket==0:
打印('bucket empty in',minutes,'minutes')
退出()
这个代码是有效的,在本例中所需的分钟数是91分钟,但我不能用这个代码来处理一个有100万块石头和500个孩子的桶

def compute_stones(minutes)
    stones = 0
    for child in children_rate:
        stones += minutes // child  # integer division
    return stones
我能看到的唯一优化是在和/加操作中转换mod操作,因为除法/乘法更昂贵。我可以使用numpy数组等等,但没有什么能真正加快进程


我试图在没有运气的情况下将这个问题改编成我的算法教科书中描述的一些典型已知问题。

你可以将算法转过来,这样在给定的分钟数内,你就可以计算出所有孩子使用了多少石头

def compute_stones(minutes)
    stones = 0
    for child in children_rate:
        stones += minutes // child  # integer division
    return stones

然后,你可以进行二进制切分,找出stones=100的分钟数。你可以做的一件事是对答案进行二进制搜索

假设答案是
X
minutes。 那你就知道在那段时间里每个孩子要带多少块石头了。 如果所取石头的总数低于预期,
X
需要更高。 否则,在下半部分搜索

代码:

children_rate = [3, 3, 5, 7, 10]
bucket = 100

lo, hi = 0, bucket * max (children_rate)
while lo < hi:
    me = (lo + hi) // 2
    if sum (me // i for i in children_rate) < bucket:
        lo = me + 1
    else:
        hi = me

print (lo)
children\u rate=[3,3,5,7,10]
桶=100
lo,hi=0,桶*最大值(儿童率)
当lo
每个孩子都会在某个时期挑选一块石头,所有的孩子都会以某个模式挑选石头,这个模式也有一个时期。这种模式的周期是每个孩子的周期。它可以用几种方法计算,但在本例中,让我们使用每个周期的因式分解

3  =   3
5  =     5
7  =       7
10 = 2 * 5

所以公共周期是
210=2*3*5*7
。在这段时间里,埃里克挑了42块石头,马克挑了21块,劳拉挑了30块,艾玛和弗兰克各挑了70块。每210分钟233块石头。如果你在一个桶里有一百万颗石头,他们会在901110分钟内挑选出999803颗石头,你会为剩下的197颗石头运行你的原始代码。很简单,不是吗?

既然问题被标记为
python-3.x
,那么地板分割不应该是
/
?即使对于一些孩子,周期也可能非常大(例如,如果他们是不同的素数整数,那么周期与所有孩子的周期乘积一样大)。所以这种方法是不切实际的,除非我们知道子周期都是非常小的整数,或者保证有一个小的LCM。