我正在努力解决下面的问题,我确信这个问题有解决办法。我不能透露太多的信息,所以我制定了它的一般术语,并提出了以下寓言。我在这里向你介绍 睡眠问题。你知道吗
Imagine a monastery where 12 monks sleep, eat, pray, or work outside the monastery. Each monk, needs to sleep 8 or 6 hours per night. Each monk has X amount where he has to work in the garden, the stall or herd the sheep (e.g, activities outside the monastery) and Y hours hangs around within the walls of the monastery during these Y hours each monk is either hanging around (e.g. praying, eating, consuming beer) or he is sleeping S hours (Y is always bigger the S).
The head of this monastery asks if there is a possible way to find a best possible sleeping arrangement such that the number of beds can be reduced, and that each monks get its required sleeping.
我对该问题的输入数据如下表所示:
time_slots_in_monastery = [
# time of the day
#14 16 18 20 22 24 2 4 6 8 10 12
(0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0),
(0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0),
(0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0),
(0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0),
(0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0),
(0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0),
(0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0),
(0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0),
(0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0),
(0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0),
(0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0),
(0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0),
]
每行代表一个和尚。数字1代表寺院内的时隙,0代表僧侣在外的时间。你知道吗
另外,我还有一个向量,包含每个人的睡眠需求 和尚。你知道吗
required_sleeping = [4, # number of sleeping slots , each one is 2 hours.
3,
3,
4,
4,
4,
4,
3,
3,
3,
3,
3]
目前的解决方案是:
solution = [
(0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0),
(0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0),
(0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0),
(0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0),
(0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0),
(0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0),
(0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0),
(0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0),
(0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0),
(0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0),
(0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0),
(0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0),
(0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0),
]
# total beds:
# 0, 0, 12, 12, 12, 5, 0, 0 , 0, 0, 0, 0
所有的僧侣晚上6点睡觉。但是如果我们让11号和尚和12号和尚使用同一张床,我们就可以把床的数量减少到11张。更好的是,1号和尚和2号和尚也可以共用一张床,然后我们把床的数量减少到10张。你知道吗
better_solution = [
(0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0),
(0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0),
(0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0),
(0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0),
(0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0),
(0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0),
(0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0),
(0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0),
(0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0),
(0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0),
(0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0),
(0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0),
]
现在有12个僧侣,这个问题可能是暴力强迫的,但实际上我有大约50个僧侣,解决的时间是5分钟,而不是2小时。因此,我正在寻找一种方法,找到一种方法来解决问题的f-最小搜索风格或任何其他方式,这是不是蛮力。你知道吗
我在这里介绍我的Python暴力解决方案:
import pprint
time_slots_in_monastery = [
# time of the day
#14 16 18 20 22 24 2 4 6 8 10 12
(0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0),
(0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0),
(0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0),
(0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0),
(0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0),
(0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0),
(0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0),
(0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0),
(0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0),
(0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0),
(0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0),
(0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0),
]
required_sleeping = [4,
3,
3,
4,
4,
4,
4,
3,
3,
3,
3,
3]
def make_new_bed(rl):
bed = '0' * rl
return bed
def search_in_beds(beds, rl, sleep_time, first, last):
sleep_slots = '0' * sleep_time
sleep = '1' * sleep_time
index = False
for cn, bed in enumerate(beds):
try:
index = bed[first:last+1].index(sleep_slots)
index += first
bed = bed[:first] + bed[first:last+1].replace(sleep_slots, sleep, 1) + bed[last+1:]
beds[cn] = bed
print()
print('monastery time from: %s to: %s' % (first, last))
print('this monk found a place in bed(%s) from (%s) to (%s)' % (cn, index, index + sleep_time-1))
print('bed(%s) time: %s ' % (cn, bed))
except:
"""
I did not found a free time in this bed
"""
pass
if index:
return index, index + sleep_time - 1
#adding a bed and searching again
beds.append(make_new_bed(rl))
return search_in_beds(beds, rl, sleep_time, first, last)
def monks_beds(t, rsleep, rl=12):
beds = []
output = []
for cn, i in enumerate(t):
sleep_time = rsleep[cn]
first = i.index(1)
last = len(i) - 1 - i[::-1].index(1)
first, last = search_in_beds(beds, rl, sleep_time, first, last)
out = rl * '0'
out = out[:first] + sleep_time * '1' + out[last:]
output.append([int(x) for x in out])
return beds
print('time_slots_in_monastery:')
pprint.pprint(time_slots_in_monastery)
print('required_sleeping')
pprint.pprint(required_sleeping)
pprint.pprint(monks_beds(time_slots_in_monastery, required_sleeping))
天真的解决方案
我能想出的一个解决办法没有考虑到“在修道院的时间”,那就是确保相邻两个僧侣的睡眠时间永远不会重叠,以我们一天的时间长度为模数:
我相信(但现在还不能正式证明)这个解决方案是最优的,因为:
所以我们需要解决的就是如何通过编程改变我们的睡眠时间,使相邻的两个时间不重叠:
相邻“寺院时间”的可能解决方案
第二个解决方案我“可以想象的工作”(但肯定不能证明是最优的)是使用相同的算法,限制在“时间在修道院”的时间,排序后的“时间在修道院”矩阵。你知道吗
首先,我会对矩阵进行排序,以便进入最早矩阵的僧侣首先:
然后对绑定的条目(僧侣同时进入)进行排序,以便最先离开的僧侣优先:
应用前面的算法,但仅限于
time_slots_in_monastery
二进制掩码:0
在Monk0
mask index0
开始睡觉1
在和尚0
停止时开始睡觉。在蒙版之外的重叠被环绕,从蒙克1
蒙版索引0
开始这个想法是让两个相邻的僧侣有尽可能多的重叠,并尽可能早地填补第一个空缺。你知道吗
这里的解决方案与上面的有点不同。我已经把和尚们的指数洗牌了,但我相信重新索引不会有问题。我相信这个解决方案是最优的。你知道吗
算法如下:
首先,我们把僧侣分成4和3两个单位。你知道吗
现在我们需要计算这些单元的数量,并为每个单元分配一张单人床。你知道吗
关于剩下的僧侣:
我们一定会把剩下的修道士消耗4个时间单位,并不断增加修道士(消耗3个时间单位),直到我们达到12个时间单位。我们给这一组分配一张床。你知道吗
我们现在必须为不属于上一个单位的其余僧侣分配一张床。你知道吗
程序如下:
结果如下:
增加更多的僧侣和不同的时间单位可以通过更仔细地观察“所需睡眠”时间来优化。所有的算法都可能围绕着优化阵列来解决。你知道吗
相关问题 更多 >
编程相关推荐