考虑以下python代码:
import math
mem={}
def get_id(A, forbidden):
count = {}
for a in A:
if a<>forbidden:
n = A[a]
count[n] = count.get(n,0)+1
return frozenset( [A.get(forbidden, 0)] + count.items() )
def class_seatings(A, forbidden=None):
if sum(A.values())==1:
if forbidden in A:
return 0
else:
return 1
ssum = 0
for a in A:
if a <> forbidden:
n = A[a]
A2 = dict(A)
if n==1:
del A2[a]
else:
A2[a] -= 1
id = get_id(A2, a)
if id not in mem:
mem[id] = class_seatings(A2, a)
cs = mem[id]
ssum += cs
return ssum
def student_seatings(A):
assert all(map(lambda x: x>0, A.values()))
facts = map(lambda x: math.factorial(x), A.values())
mult = reduce(lambda x,y: x*y, facts, 1)
return mult*class_seatings(A) % 1000000007
看起来它得到了正确的基本情况:
>>> student_seatings( {1:1, 2:2} )
2
>>> student_seatings( {1:1, 2:2, 3:3} )
120
>>> student_seatings( {1:1, 2:3} )
0
>>> student_seatings( {1:2, 2:2} )
8
mem
但是,在您提到的要求之前,使用and的基本记忆方案get_id
开始崩溃。要看到这一点,请观看进度
mem={}
for upper in range(2,11):
A = dict( (x,x) for x in range(1,upper) )
print len(A), student_seatings(A)
print len(mem)
产生
1 1
0
2 2
4
3 120
20
4 309312
83
5 579005048
329
6 462179000
1286
7 481882817
5004
8 678263090
19447
9 992777307
75581
有人关心改进它吗?