我会使用一个简单的回溯算法。使用 Python 生成器函数:
def calc_gifts(names, blacklist, gifts={}):
if len(names) > 0:
name, rest = names[0], names[1:]
for other in names + list(gifts):
if (other != name and
other not in blacklist[name] and
(other not in gifts or gifts[other] != name) and
other not in gifts.values()):
gifts_new = dict(gifts.items() + [(name, other)])
for solution in calc_gifts(rest, blacklist, gifts_new):
yield solution
else:
yield gifts
现在,我们设置名称和黑名单,并让生成器生成解决方案:
all_names = ["john", "james", "jenna", "joseph", "jane", "jacob", "joanne"]
blacklist = {"john": ["james", "jane"],
"james": ["jenna"],
"jenna": ["joseph"],
"joseph": ["jane"],
"jane": ["jacob", "john"],
"jacob": ["joanne"],
"joanne": ["john"]}
generator = calc_gifts(all_names, blacklist)
solution = next(generator)
solution
then 是dict
送礼者和接受者的一个,例如{'joanne': 'joseph', 'james': 'john', 'jane': 'joanne', 'joseph': 'jacob', 'jacob': 'jane', 'john': 'jenna', 'jenna': 'james'}
.
对于第一个解决方案,即 using next(generator)
,calc_gifts
仅调用了 10 次;对于所有 224 个解决方案,例如使用list(generator)
它被调用大约。1000 次。