假设参加一个婚礼,要安排作为,一些宾客是朋友,一些宾客是敌人,宾客列表如下
约束:
①朋友之间要坐在一起
②敌人之间不能坐在一起
如何用ortools得到解决方案,一共需要几张桌子?
一张桌子坐几个人
可以写一段代码来模拟这个人员安排的过程
# -*- coding:utf-8 -*- # author:jxjxjjxjxjxj # 基本思路:模拟————————朋友相遇:2;敌人相遇:-1;其他:0 ,让结果为最大值即可 from openpyxl import load_workbook import copy import random # 定义桌子,一张桌子最多可以坐self.numbers 个人 class Table: def __init__(self): self.numbers = 4 # 指定了一张桌子可以坐4个人,可根据实际修改, self.relationship = 0 self.guests = [] self.score = 0 # 保存上一次调用函数计算出的成员添加分数,减少重复计算 def get_score(self, guest): result = 0 if len(self.guests) == 0: pass elif len(self.guests) >= self.numbers: result = -1 else: for i in self.guests: if self.add(i, guest) >= 0: result += self.add(i, guest) else: result = -1 self.score = result return result def addGuest(self, guest): self.relationship += self.score self.guests.append(guest) #模拟逐个分配过程中客人相遇情形 def add(self, guest_1, guest_2): if guest_1['Guests'] in guest_2['Friends']: result = 2 elif guest_1['Guests'] in guest_2['Enemies']: result = -1 else: result = 0 return result # 定义一个方案 class Tables: def __init__(self): self.tables = [] self.tables.append(Table()) self.guest = 0 # 保留上一次调用函数要添加的宾客(但是还没添加) def add_table(self): table = Table() self.tables.append(table) def get_relationship(self): relationship = 0 for table in self.tables: relationship += table.relationship return relationship def get_score(self, guest): self.guest = guest scores = {} new_scores = {} for i in range(len(self.tables)): score = self.tables[i].get_score(guest) scores[i] = score score_max = max(scores.values()) for i in scores: if scores[i] == score_max: new_scores[i] = score_max return new_scores def addGuest(self, i): # i 表示对第几张桌子进行添加客人 self.tables[i].addGuest(self.guest) # 如果将一个人加入进去得到的是同样的情况,那么就创建新的tables class Test: def __init__(self, guests): self.schedules = [] self.guests = guests self.schedules.append(Tables()) def addSchedule(self, schedule): self.schedules.append(schedule) # 专门进行scores的处理 def score_analysis(self, schedule, scores): if len(scores.values()) == 1 and list(scores.values())[0] > -1: schedule.addGuest(list(scores.keys())[0]) elif list(scores.values())[0] == -1: schedule.add_table() schedule.addGuest(len(schedule.tables) - 1) else: schedule.addGuest(list(scores.keys())[0]) del scores[list(scores.keys())[0]] for i in scores: new_schedule = copy.deepcopy(schedule) new_schedule.addGuest(i) self.addSchedule(new_schedule) def run(self): for guest in self.guests: for schedule in self.schedules: scores = schedule.get_score(guest) self.score_analysis(schedule, scores) def show_schedule(self): i = 1 for schedule in self.schedules: print("————————第{}种分配方案,共需要{}安排桌,关系指数:{}——————————".format(i, len(schedule.tables), schedule.get_relationship())) i += 1 for table in schedule.tables: print(table.guests) def main(): # 读取数据 wb = load_workbook('C:\\Users\\Administrator\\Desktop\\婚礼宾客关系表.xlsx') ws = wb.active content_list = [] for col in ws.iter_cols(min_row=1, max_col=3, values_only=True): content_list.append(list(col)) # 求出最优解对应的relationship_index的值 friends = ",".join(content_list[1][1:]).split(",") # 表格中出现的多个人名使用英文","分隔 relationship_index = 0 for i in friends: if i != '-': relationship_index += 1 for i in range(len(content_list)): for j in range(len(content_list[0])): if ',' in content_list[i][j]: content_list[i][j] = content_list[i][j].split(',') guests = [] for i in range(1, len(content_list[0])): guest = {} guest[content_list[0][0]] = content_list[0][i] guest[content_list[1][0]] = content_list[1][i] guest[content_list[2][0]] = content_list[2][i] guests.append(guest) # 进行模拟分配方案,分配结果与表格中人名的先后顺序有关,一般经过少数几次模拟即可得出一个或几个最优解 print("*" * 100) print("该方案的关系指数最优值等于:{}".format(relationship_index)) for i in range(5): # 进行5次模拟分配,如果希望得到更多的解,可增加模拟次数 print("***************第{}次模拟*******************\n".format(i + 1)) random.shuffle(guests) test = Test(guests) test.run() test.show_schedule() main()
数据源是这样的
进行5次模拟得到的结果如下,包含最优解(这个是截图,右边有一点看不到)
谢谢,需要用ortools,这些都没用到ortools