<p>这里的关键是:</p>
<p><code>Actually, a crew can't work 7 consecutive days. In every 7 days, there must be 1 day-off.</code></p>
<p>改写问题,每7天随机抽取2天(或根据需要将一个月分成四段时间)。然后保证你的分配是均匀的。按照Martijn Pieters的建议使用<code>random.sample()</code>。在</p>
<p>你可以从第一周开始使用这种方法生成两个值,如果你想一个接一个的话,就按顺序生成它们。在</p>
<p><strong>编辑:</strong></p>
<p>正如tcaswell所观察到的,仍然有一些情况下你会连续工作十天。为了解决这一问题,您可以每三天安排一天休假,创建一个10天的列表,并从不会使连续7天标准失效的天数子集中随机删除两天。在</p>
<p>或者,您可以继续使用原始算法生成列表,直到它符合条件为止,因为无论如何您都很可能得到一个有效的解决方案。你必须编写一个验证函数,但是这很容易做到,因为你只是在计算最长的连续天数。在</p>
<p><strong>代码:</strong></p>
<p>第二种选择的实现。在</p>
<pre><code>import random
from itertools import chain
from itertools import count
def candidate(m):
''' Returns 2 days per week, in m days, where m is the length of the month. '''
weeks = weeksmaker(m)
return sorted(list(chain(*[random.sample(week, 2) for week in weeks])))
def weeksmaker(m):
''' Divides a month up into four weeks, randomly assigning extra days to weeks. '''
weeks = [range(i, i+7) for i in xrange(1,29,7)]
for i in range(m - 28):
weeks[random.randint(1, len(weeks))-1].append(i)
c = count(1)
return [[c.next() for day in week] for week in weeks]
def valid(days, c):
''' Validity check. Cant work more than c consecutive days. '''
for i in xrange(1, len(days)):
if days[i] - days[i-1] > c:
return False
else:
return True
def daysoff(m, n, c):
''' In month length m, need n days off, cant work more than c consecutive days. '''
while True:
days = candidate(n)
if valid(days, c):
return days
>>> for i in range(28, 32):
... daysoff(i, 8, 7)
...
[6, 7, 10, 14, 18, 20, 27, 28]
[4, 7, 10, 13, 19, 21, 23, 24]
[2, 4, 9, 13, 15, 20, 25, 27]
[1, 3, 9, 12, 18, 19, 24, 28]
</code></pre>