I have troubles solving the following Problem for a class-trip:
There are 54 students who have to be divided into 14 3-bed rooms and 6 2-bed rooms. Each person has one or more favorites with whom he/she would like to share a room.
preferences = {'studen1': [studnet2, student3], 'student2': [student3, student 1], ...}
I was able to calculate every possible triple match (in a group of 3 students everyone likes each other back) and normal match (in a group of 2 students everyone likes each other back)
I thought about maybe trying to calculate every possible combinations of students (or at least the preverences) and try to get the best result by providing points based on how good the rooms are: good 3-person room: 6 points good 2 room: 4 points average 3-person room: 5 points average 3-bed room: 4 points medium bad 3 room: 3 points bad 3er room: 2 points very bad 3-bed room: 1 point medium 2 room: 1 point
Now I am sorta overwhelmed an don't know how to approach the problem without having the need of using a super-computer ;)
I am sorry for my very bad code ;) this is my code after calculating the normal and triple matches:
students_with_room = []
real_rooms = []
exit_loop = False
real_rooms = {'2A': [], '2B': [], '2C': [], '2D': [], '2E': [], '2F': [],'3A': [], '3B': [], '3C': [], '3D': [], '3E': [], '3F': [], '3G': [], '3H': [], '3I': [], '3J': [], '3K': [], '3L': [], '3M': [], '3N': [],}
for student in students:
if student not in students_with_room:
if triple_matches[student] == None:
for room in real_rooms:
if real_rooms[room] == [] and '2' in room:
if len(matches[student]) != 0:
for i in range(len(matches[student])):
if len(set([matches[student][i], student]).intersection(students_with_room)) == 0:
real_rooms[room] = [matches[student][i], student]
students_with_room = students_with_room + [matches[student][i]]
students_with_room = students_with_room + [student]
exit_loop = True
break
else:
pass
else:
pass
if exit_loop == True:
break
if real_rooms[room] == [] and '3' in room:
pass
exit_loop = False
else:
for room in real_rooms:
if student not in students_with_room:
if real_rooms[room] == [] and '3' in room:
real_rooms[room] = [triple_matches[student][0], triple_matches[student][1], student]
students_with_room = students_with_room + triple_matches[student]
students_with_room = students_with_room + [student]
else:
pass
for triple_match in triple_matches:
already_done = False
if triple_matches[student] == None:
pass
else:
if student in students_with_room:
already_done = True
if not already_done:
students_with_room.append(triple_matches[student][0])
real_rooms
Alright so this problem seemed kind of interesting, here is an example of a simple but brute force solution using
networkx. Note that this will run slowly once your number of students grows to be large. I would still recommend treating this as a multiple knapsacks problem, but hopefully this enough to get you thinking about the problem a little differently.Where here,
sis our final allowable combinations, and the key with the largest weight would be our optimal solution -- i.e. the room allocation with the happiest students.Edit: Apologies, I misread the original question, I did not realize you had set student number assignments between rooms, this should address that.