您可以生成所有可能的堆栈弹出列表,然后进行模拟:
但是,会有重复,请考虑每个堆栈上只有两个元素的情况。如果将 a 推送到 c 并将 b 推送到 d,则它们被推送的顺序无关紧要。
def simulate(steps):
source={'a':range(4),'b':range(4,8)}
res = {'c':"",'d':""};
for i,step in enumerate(steps):
res[step[1]]+=str(source[step[0]].pop())
# this is what each stack will look like
return res['c']+'-'+res['d']
def steps(a_left,b_left):
ret = []
if a_left>0:
substeps = steps(a_left-1,b_left)
ret.extend( [ x + [('a','c')] for x in substeps] )
ret.extend( [ x + [('a','d')] for x in substeps] )
if b_left>0:
substeps = steps(a_left,b_left-1)
ret.extend( [ x + [('b','c')] for x in substeps] )
ret.extend( [ x + [('b','d')] for x in substeps] )
if(len(ret)==0):
return [[]]
return ret;
结果:
>>> [x for x in steps(1,1)]
[[('b', 'c'), ('a', 'c')], [('b', 'd'), ('a', 'c')], [('b', 'c'), ('a', 'd')], [
('b', 'd'), ('a', 'd')], [('a', 'c'), ('b', 'c')], [('a', 'd'), ('b', 'c')], [('
a', 'c'), ('b', 'd')], [('a', 'd'), ('b', 'd')]]
>>> [simulate(x) for x in steps(1,1)]
['73-', '3-7', '7-3', '-73', '37-', '7-3', '3-7', '-37']
>>> len(set([simulate(x) for x in steps(4,4)]))
5136
如果我们考虑只有一个目标堆栈的两个堆栈,我们可以在 (2*n)!/(n!)^2 处找到唯一堆栈的数量。这与 8 个元素的排列数相同,其中 4 个是“A”,其中 4 个是“B”。然后我们可以通过将它们划分为子集来将它们分配给每个单独的堆栈 - 每个堆栈具有 N 个唯一编号的子集的数量将是 2^(2^n)
(2^(2*n))/((2*n)!/(n!)^2)
不过,我看不出有什么方法可以更有效地生成这些。