给定{1 .... n}上的关系〜具有x~y暗示x&lt; y,这个算法生成所有排列a [1] .... a [n]并且它们反转a&#39; [1] ..... a&#39; [n]具有a&#39; [ j]&lt;每当j~k时a&#39; [k]。为方便起见,我们假设a [0] = 0且0≤k表示1 <= k <= n。
V1。 [初始化。]设置a [j]&lt; - j和a&#39; [j]&lt; -j为0&lt; = j&lt; = n。
V2。 [访问。]访问排列a [1] ... a [n]及其逆a&#39; [1] ... a&#39; [n]。然后设置k&lt; - n。
V3。 [可以向左移动吗?]设置j&lt; - a&#39; [k]和l&lt; -a [j-1]。如果l~k,请转到V5。
V4。 [是的,移动它。]设置[j-1]&lt; - k,a [j]&lt; -l,a&#39; [k]&lt; -j-1和&#39; [l] &lt; - j。转到V2。
V5。 [不,把k放回去。]当j&lt; k,设置l&lt; -a [j + 1],a [j]&lt; -1,a&#39; [l]&lt; -j,并且j&lt; -j + 1。 然后设置[k]&lt; -a&#39; [k]&lt; -k。如果k> 1,则将k减1并返回V3。 0
已经尝试过实施但是与流程混淆了。请解释此算法的流程及其如何工作基于优先约束,例如1~2表示{1,2,3}。
答案 0 :(得分:0)
Knuth,祝福他,是一位未经构建的汇编语言程序员。以下是将此算法呈现为经过测试的无goto Python。 precedes
是关系~
。
from itertools import permutations
def topological_orders(n, precedes):
a = list(range(n + 1))
ai = a[:]
while True:
yield tuple(a[1:])
k = n
while True:
j = ai[k]
l = a[j - 1]
if not precedes(l, k):
a[j - 1] = k
a[j] = l
ai[k] = j - 1
ai[l] = j
break
while j < k:
l = a[j + 1]
a[j] = l
ai[l] = j
j += 1
a[k] = ai[k] = k
k -= 1
if not k > 0:
return
def test(n, precedes):
fast_orders = set()
for order in topological_orders(n, precedes):
print(order)
fast_orders.add(order)
slow_orders = set()
for order in permutations(range(n + 1)):
if not any(precedes(order[i], order[j]) for i in range(n + 1) for j in range(i)):
slow_orders.add(order[1:])
assert fast_orders == slow_orders
if __name__ == '__main__':
def divides(a, b):
return a < b and (a == 0 or b % a == 0)
test(6, divides)
在您的输入中,我们从
开始0123.
访问123
并向左移动3
。
0132
访问132
并向左移动3
。
0312
访问312
。我们无法移动3
,因为0 ~ 3
。将其一直向右移动并尝试移动2
。
0123
我们无法移动2
,因为1 ~ 2
。尝试移动1
。我们无法移动1
,因为0 ~ 1
。尝试移动0
- 哎呀,我们已经完成了。