我被下面的难题困住了。需要你的帮助来解决这个问题:有8个人在一家酒店预定了7个房间,并决定只使用这7个房间中的4个,方法是让两个人的组合在7天内不会重复,也不会让一个人在一个房间里呆两次。例如,如果1& 2,3& 4,5& 6和7& 8留在房间1,房间2,房间3和房间4,那么这些组合永远不会呆在一起。他们必须做出不同的组合,并改变房间。另一个例子,我不能再和任何人呆在1号房间,这也适用于其他人。
有谁能帮我解决这个7x7矩阵吗?感谢您的努力!
1&2 6&7 3&8 4&5
5&6 1&3 4&8 2&7
5&7 1&4 2&8 3&6
7&8 2&3 1&5 4&6
2&4 5&8 3&7 1&6
3&4 6&8 2&5 1&7
2&6 4&7 3&5 1&8
程序:)
一个解决方案是:
18 36 27 45
35 17 46 28
47 25 16 38
26 37 15 48
58 23 14 67
68 24 57 13
34 78 56 12
实际上,这是两个解,因为你可以阅读行代表天,列代表房间,反之亦然。分配给人们的每一个数字的排列,每一个房间(列)的排列,每一个日期(行)的排列,也会导致另一个解决方案。
以下是Python代码,基于Egor Skriptunoff的解决方案。主要思想是相同的:生成所有成对的人的列表,并开始将他们一次一个地放在黑板上。如果没有有效的位置,那么就回溯并尝试其他内容。在下面的代码中,
tasks
的列表记录了董事会状态,因此当到达死胡同时,下一个候选董事会状态将从tasks
列表中弹出。关键在于以一种有组织、有效的方式列举所有的可能性。
有一些小的区别:
- 这段代码是迭代的,而不是递归的。
-
solve
函数尝试生成所有解,而不是在找到一个解后停止。 - 为简单起见,删除了初始化条件。
import itertools as IT
import collections
import copy
import random
people = range(1, 9)
days = range(7)
rooms = range(7)
pairs = list(IT.combinations(people, 2))
def solve():
board = [[None for room in rooms] for day in days]
pairidx = 0
tasks = [(pairidx, board)]
while tasks:
pairidx, board = tasks.pop()
if pairidx == len(pairs):
yield board
continue
for day, room in IT.product(days, rooms):
if not (used_day(board, pairidx, day)
or used_room(board, pairidx, room)
or used_day_room(board, day, room)):
tasks.append(
(pairidx + 1, move(board, pairidx, day, room)))
def used_day(board, pairidx, day):
"""
Return True if any person in persons has already been assigned a room
"""
return any([person in pairs[idx] for idx in board[day] if idx is not None
for person in pairs[pairidx]])
def used_room(board, pairidx, room):
"""
Return True if any person in persons already been in the room
"""
return any([person in pairs[row[room]] for row in board if row[room] is not None
for person in pairs[pairidx]])
def used_day_room(board, day, room):
"""
Return True if the room has already been assigned a pair for the day
"""
return board[day][room] is not None
def move(board, pairidx, day, room):
"""
Assign a pair to a room on a given day. Return the new (copy) of the board.
"""
board = copy.deepcopy(board)
board[day][room] = pairidx
return board
def report(board):
print('n'.join(
[' '.join([''.join(map(str, pairs[col])) if col is not None else
' ' for col in row])
for row in board]))
print('-' * 20)
for solution in solve():
report(solution)
顺便说一下,这个问题与斑马问题和其他约束难题非常相似。