I'm having trouble with SPOJ Problem 423: Assignments.
The problem asks me to count the number of possible assignments for n unique topics to n unique students so that each student gets exactly one topic that he/she likes. I have come up with a way to parse the input into a list of lists called preferences
. Each inner list is a list of topics (denoted by an integer between 0 and n-1 inclusive) that one student likes.
For example for the input:
1 1 1
1 1 1
1 1 1
I get [[0, 1, 2], [0, 1, 2], [0, 1, 2]]
.
And for the input:
1 0 0 1 0 0 0 0 0 1 1
1 1 1 1 1 0 1 0 1 0 0
1 0 0 1 0 0 1 1 0 1 0
1 0 1 1 1 0 1 1 0 1 1
0 1 1 1 0 1 0 0 1 1 1
1 1 1 0 0 1 0 0 0 0 0
0 0 0 0 1 0 1 0 0 0 1
1 0 1 1 0 0 0 0 0 0 1
0 0 1 0 1 1 0 0 0 1 1
1 1 1 0 0 0 1 0 1 0 1
1 0 0 0 1 1 1 1 0 0 0
I get the list [[0, 3, 9, 10], [0, 1, 2, 3, 4, 6, 8], [0, 3, 6, 7, 9], [0, 2, 3, 4, 6, 7, 9, 10], [1, 2, 3, 5, 8, 9, 10], [0, 1, 2, 5], [4, 6, 10], [0, 2, 3, 10], [2, 4, 5, 9, 10], [0, 1, 2, 6, 8, 10], [0, 4, 5, 6, 7]]
.
Now what I need to do is count the number of ways I can select a unique number from each inner list so that no element is selected twice and each number between 0 and n-1 inclusive is selected exactly once among all selections. For the first example input, this is trivial, it's 3! = 6
. But in the second example, it is hard for me to figure out a way to count the number of valid selections. They give the answer as 7588 for the second input but I don't know how to reach that answer.
I already tried the brute force method of finding all permutations of [0,...,n-1] and trying to see if they are valid combinations based on set membership but it was far too slow and it literally crashed my computer when I tried to iterate through the 11! = 39916800
permutations. So what I need to do is find a more efficient method of counting this.
Here is my code so far. All it currently does is parse the input from stdin into a list of lists called preferences and print it to stdout.
def main():
t = int(raw_input())
from itertools import repeat
for _ in repeat(None, t):
n = int(raw_input())
preferences = [[] for _ in repeat(None, n)]
for student in xrange(n):
row = map(int, raw_input().split())
for i in xrange(len(row)):
if row[i] == 1:
preferences[student].append(i)
print preferences
if __name__ == '__main__':
main()
Is there any method I can use to count this efficiently? Any hints/tips are welcome. I don't expect anyone to solve the problem for me. I am just confused as to how I should approach this.