aabbcc本质不同的排列数

 
aabbcc本质不同的排列数
Stainhaus在其名著《一百个数学问题》中给出了如下问题:
“由aabbcc这组字母可以得出90种不同的排列,其中有些如aabcbc、aacbcb、bcbcaa及acacbb之间 并无本质差别,因为c、b互换,则可由第一个排列得出第2个排列,若逆向看第2个排列,可以发现它与第三个排列等价;而在第3个排列中,若将a、b互换,则生成第4个排列,我们将这种无本质差别的排列看成是相同类型的排列,而排列aabcbc和abcabc这两个排列无论用字母替换法还是逆向阅读法,甚至交替使用,也不能将前一种排列变为后一种,所以我们将这样的排列称为不同类型的排列。试问:aabbcc这6个字母共能组成多少种本质不同的排列类型。”
~~~~~~~~~~~~~~
多重元素集合的排列生成法
多重元素集合是指集合中一个元素可以重复出现多次的集合。例如多重元素集合{1,2,2,3,3,3}中元素1出现1次,2出现2次,3出现3次,而多重元素集合{1,1,2,2,3,3}中元素1、2、3均出现2次。多重元素集合的排列是指所有集合元素所构成的一个排列,一个元素在集合中出现几次,它在排列中同样要出现几次,例如,多重元素集合{1,1,2,2}共有6个不同的排列,它们分别是:
1122
1212
1221
2112
2121
2211
若一个集合中含k1个a1,k2个a2,…,kn个an,则该多重集合的不同排列数为:
(k1+k2+…+kn)!/k1!k2!...kn!
下面我们考虑多重元素集合的排列枚举算法。
我们将元素为表的表称为二重表,多重元素的集合可以表示成二重表的形式。例如,多重元素集合{1,2,2,3,3,3}表示成二重表[[1],[2,2],[3,3,3]]的形式。
domains
 ilist=integer*
 ilists=ilist*
 
predicates
 nondeterm dup_perm(ilists, ilist)
 nondeterm dup_perm_3(ilists, ilist, ilist)
 nondeterm merge(ilist, ilist, ilist)
 
clauses
 dup_perm([], []).
 dup_perm([L|Ls], P):-dup_perm_3(Ls, L, P).
 
 dup_perm_3([], P, P).
 dup_perm_3([L|Ls], P0, P):-
      merge(L, P0, P1),
      dup_perm_3(Ls, P1, P).
     
 merge([], L, L):-!.
 merge(L, [], L):-!.
 merge([X|L1], L2, [X|L]):-merge(L1, L2, L).
 merge(L1, [X|L2], [X|L]):-merge(L1, L2, L).
 
goal
 dup_perm([[1,1],[2,2],[3,3]], P),
 write(P), nl,
 fail.
上述目标生成的全部解为:

[3,3,2,2,1,1]
[3,2,3,2,1,1]
[3,2,2,3,1,1]
[3,2,2,1,3,1]
[3,2,2,1,1,3]
[2,3,3,2,1,1]
[2,3,2,3,1,1]
[2,3,2,1,3,1]
[2,3,2,1,1,3]
[2,2,3,3,1,1]
[2,2,3,1,3,1]
[2,2,3,1,1,3]
[2,2,1,3,3,1]
[2,2,1,3,1,3]
[2,2,1,1,3,3]
[3,3,2,1,2,1]
[3,2,3,1,2,1]
[3,2,1,3,2,1]
[3,2,1,2,3,1]
[3,2,1,2,1,3]
[2,3,3,1,2,1]
[2,3,1,3,2,1]
[2,3,1,2,3,1]
[2,3,1,2,1,3]
[2,1,3,3,2,1]
[2,1,3,2,3,1]
[2,1,3,2,1,3]
[2,1,2,3,3,1]
[2,1,2,3,1,3]
[2,1,2,1,3,3]
[3,3,2,1,1,2]
[3,2,3,1,1,2]
[3,2,1,3,1,2]
[3,2,1,1,3,2]
[3,2,1,1,2,3]
[2,3,3,1,1,2]
[2,3,1,3,1,2]
[2,3,1,1,3,2]
[2,3,1,1,2,3]
[2,1,3,3,1,2]
[2,1,3,1,3,2]
[2,1,3,1,2,3]
[2,1,1,3,3,2]
[2,1,1,3,2,3]
[2,1,1,2,3,3]
[3,3,1,2,2,1]
[3,1,3,2,2,1]
[3,1,2,3,2,1]
[3,1,2,2,3,1]
[3,1,2,2,1,3]
[1,3,3,2,2,1]
[1,3,2,3,2,1]
[1,3,2,2,3,1]
[1,3,2,2,1,3]
[1,2,3,3,2,1]
[1,2,3,2,3,1]
[1,2,3,2,1,3]
[1,2,2,3,3,1]
[1,2,2,3,1,3]
[1,2,2,1,3,3]
[3,3,1,2,1,2]
[3,1,3,2,1,2]
[3,1,2,3,1,2]
[3,1,2,1,3,2]
[3,1,2,1,2,3]
[1,3,3,2,1,2]
[1,3,2,3,1,2]
[1,3,2,1,3,2]
[1,3,2,1,2,3]
[1,2,3,3,1,2]
[1,2,3,1,3,2]
[1,2,3,1,2,3]
[1,2,1,3,3,2]
[1,2,1,3,2,3]
[1,2,1,2,3,3]
[3,3,1,1,2,2]
[3,1,3,1,2,2]
[3,1,1,3,2,2]
[3,1,1,2,3,2]
[3,1,1,2,2,3]
[1,3,3,1,2,2]
[1,3,1,3,2,2]
[1,3,1,2,3,2]
[1,3,1,2,2,3]
[1,1,3,3,2,2]
[1,1,3,2,3,2]
[1,1,3,2,2,3]
[1,1,2,3,3,2]
[1,1,2,3,2,3]
[1,1,2,2,3,3]

问题总共有90个解,即6!/2!2!2!.
~~~~~~~~~~~~~~~~~~~~~~~~~~
如何产生112233所有本质不同的排列?
我们首先定义两个排列的字典序:
a(1)a(2)…a(n)<b(1)b(2)…b(n) iff 存在k,1≤k≤n,使得a(1)=b(1),a(2)=b(2),…,a(k-1)=b(k-1)且a(k)<b(k)
一个排列称为基本解,如果它经过群S3元素及排列逆序变换反复作用后,不会变换为字典序更小的排列。
由于两次逆序变换将一个排列变成自身,因此,我们可以按照下面的方法来判断一个排列是否基本解:
(1)       在群S3元素的作用下,该排列字典序是否会减小?如果减小,则该排列不是基本解。判断的方法是:在排列中,1、2、3的首次出现次序是1在最前面,2其次,3在最后;
(2)       对排列进行逆序变换,然后将其最小化。所谓最小化,是指对逆序变换的排列进行变换(变换取自S3),使得1、2、3的首次出现次序按从小到大的次序排列。如果最小化后的排列比原排列字典序小,则原排列不是基本解。
对于上述问题进行手工验算。首先,我们考虑判断原则(1),则基本解只需在下面15个解中寻找:

[1,2,3,3,2,1]
[1,2,3,2,3,1]
[1,2,3,2,1,3]
[1,2,2,3,3,1]
[1,2,2,3,1,3]
[1,2,2,1,3,3]
[1,2,3,3,1,2]
[1,2,3,1,3,2]
[1,2,3,1,2,3]
[1,2,1,3,3,2]
[1,2,1,3,2,3]
[1,2,1,2,3,3]
[1,1,2,3,3,2]
[1,1,2,3,2,3]
[1,1,2,2,3,3]

利用判断原则(2),我们找到问题的11个基本解。
 
逆序变换
最小化变换
最小化结果
是否基本解?
123321
123321
(1)(2)(3)
123321
基本解
123231
132321
(23)
123231
基本解
123213
312321
(123)
123132
 
122331
133221
(23)
122331
基本解
122313
313221
(123)
121332
 
122133
331221
(123)
112331
 
123312
213321
(12)
123312
基本解
123132
231321
(132)
123213
基本解
123123
321321
(13)
123123
基本解
121332
233121
(132)
122313
基本解
121323
323121
(13)
121323
基本解
121233
332121
(13)
112321
 
112332
233211
(132)
122133
基本解
112323
323211
(13)
121233
基本解
112233
332211
(13)
112233
基本解
基本解的判断程序如下:
domains
 ilist=integer*
 ilists=ilist*
 tr=t(integer,integer)
 trlist=tr*
 
predicates
 nondeterm dup_perm(ilists, ilist)
 nondeterm dup_perm_3(ilists, ilist, ilist)
 nondeterm merge(ilist, ilist, ilist)
 
 nondeterm aabbcc(ilist)
 nondeterm is_primary_perm(ilist)
 nondeterm check1(ilist)
 nondeterm check2(ilist)
 
 nondeterm reverse(ilist, ilist)
 nondeterm reverse_3(ilist, ilist, ilist)
 
 nondeterm le(ilist, ilist)
 
 nondeterm s3(integer, trlist)
 nondeterm trans(trlist, ilist, ilist)
 nondeterm find_trans_member(tr, trlist)
 
clauses
 aabbcc(P):-
      dup_perm([[1,1],[2,2],[3,3]], P),
      is_primary_perm(P).
 
 is_primary_perm(P):-
      check1(P),
      check2(P).
 
 check1(P):-
      s3(1, T1), trans(T1, P, P1), le(P,P1),
      s3(2, T2), trans(T2, P, P2), le(P,P2),
      s3(3, T3), trans(T3, P, P3), le(P,P3),
      s3(4, T4), trans(T4, P, P4), le(P,P4),
      s3(5, T5), trans(T5, P, P5), le(P,P5),
      s3(6, T6), trans(T6, P, P6), le(P,P6).
 
 check2(P):-
      reverse(P,R),
      s3(1, T1), trans(T1, R, R1), le(P,R1),
      s3(2, T2), trans(T2, R, R2), le(P,R2),
      s3(3, T3), trans(T3, R, R3), le(P,R3),
      s3(4, T4), trans(T4, R, R4), le(P,R4),
      s3(5, T5), trans(T5, R, R5), le(P,R5),
      s3(6, T6), trans(T6, R, R6), le(P,R6).
 
 reverse(L, R):-reverse_3(L, [], R).
 
 reverse_3([H|L], T, R):-
    reverse_3(L, [H|T], R).
 reverse_3([], R, R).
 
 le([],[]).
 le([X1|_], [X2|_]):-X1 < X2.
 le([X|L1], [X|L2]):-le(L1, L2).
 
 s3(1, [t(1,1), t(2,2), t(3,3)]).
 s3(2, [t(1,1), t(2,3), t(3,2)]).
 s3(3, [t(1,2), t(2,1), t(3,3)]).
 s3(4, [t(1,2), t(2,3), t(3,1)]).
 s3(5, [t(1,3), t(2,1), t(3,2)]).
 s3(6, [t(1,3), t(2,2), t(3,1)]).
 
 trans(_, [], []).
 trans(T, [X|P1], [Y|P2]):-
      find_trans_member(t(X,Y), T),
      trans(T, P1, P2).
     
 find_trans_member(t(X,Y), [t(X,Y)|_]):-!.
 find_trans_member(t(X,Y), [t(Z,_)|T]):-
      X <> Z,
      find_trans_member(t(X,Y), T).
     
 
 dup_perm([], []).
 dup_perm([L|Ls], P):-dup_perm_3(Ls, L, P).
 
 dup_perm_3([], P, P).
 dup_perm_3([L|Ls], P0, P):-
      merge(L, P0, P1),
      dup_perm_3(Ls, P1, P).
     
 merge([], L, L):-!.
 merge(L, [], L):-!.
 merge([X|L1], L2, [X|L]):-merge(L1, L2, L).
 merge(L1, [X|L2], [X|L]):-merge(L1, L2, L).
 
goal
 aabbcc(P),
 write(P), nl,
 fail.
上述目标生成的全部11个解,这与我们分析的结果是一致的:
[1,2,3,3,2,1]
[1,2,3,2,3,1]
[1,2,2,3,3,1]
[1,2,3,3,1,2]
[1,2,3,1,3,2]
[1,2,3,1,2,3]
[1,2,1,3,3,2]
[1,2,1,3,2,3]
[1,1,2,3,3,2]
[1,1,2,3,2,3]
[1,1,2,2,3,3]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

上述程序是有局限的,我们枚举了S3的所有元素,并采用一种特殊的数据结构来简化问题求解的逻辑。如何将上述程序进行修改,使之适应于任意多重元素集合本质不同的排列的枚举,可以进一步探讨。但是上述程序适应于3个元素任意多重排列的情况,例如,当每个元素均为3重时,我们要求111222333本质不同的排列,可以修改aabbcc谓词为:
 aabbcc(P):-
      dup_perm([[1,1,1],[2,2,2],[3,3,3]], P),
      is_primary_perm(P).
程序运行生成全部148个解:

[1,2,2,2,1,3,3,3,1]
[1,2,3,2,1,3,3,2,1]
[1,2,3,2,1,3,2,3,1]
[1,2,2,3,3,1,3,2,1]
[1,2,2,3,3,1,2,3,1]
[1,2,2,3,3,1,2,1,3]
[1,2,2,3,1,3,3,2,1]
[1,2,2,3,1,3,2,3,1]
[1,2,2,3,1,3,2,1,3]
[1,2,2,3,1,2,3,3,1]
[1,2,2,1,3,3,3,2,1]
[1,2,2,1,3,3,2,3,1]
[1,2,2,1,3,3,2,1,3]
[1,2,2,1,3,2,3,3,1]
[1,2,2,1,2,3,3,3,1]
[1,2,3,3,2,1,1,2,3]
[1,2,3,2,3,1,3,1,2]
[1,2,3,2,3,1,1,3,2]
[1,2,3,2,3,1,1,2,3]
[1,2,3,2,1,3,3,1,2]
[1,2,3,2,1,3,1,3,2]
[1,2,2,3,3,3,1,1,2]
[1,2,2,3,3,1,3,1,2]
[1,2,2,3,3,1,1,3,2]
[1,2,2,3,3,1,1,2,3]
[1,2,2,3,1,3,3,1,2]
[1,2,2,3,1,3,1,3,2]
[1,2,2,3,1,3,1,2,3]
[1,2,2,3,1,1,3,3,2]
[1,2,2,1,3,3,3,1,2]
[1,2,2,1,3,3,1,3,2]
[1,2,2,1,3,3,1,2,3]
[1,2,2,1,3,1,3,3,2]
[1,2,2,1,1,3,3,3,2]
[1,2,3,3,1,2,2,3,1]
[1,2,3,3,1,2,2,1,3]
[1,2,3,1,3,2,3,2,1]
[1,2,3,1,3,2,2,3,1]
[1,2,3,1,3,2,2,1,3]
[1,2,3,1,2,3,3,2,1]
[1,2,3,1,2,3,2,3,1]
[1,2,3,1,2,3,2,1,3]
[1,2,1,3,3,3,2,2,1]
[1,2,1,3,3,2,3,2,1]
[1,2,1,3,3,2,2,3,1]
[1,2,1,3,3,2,2,1,3]
[1,2,1,3,2,3,3,2,1]
[1,2,1,3,2,3,2,3,1]
[1,2,1,3,2,3,2,1,3]
[1,2,1,3,2,2,3,3,1]
[1,2,1,3,2,2,3,1,3]
[1,2,1,2,3,3,3,2,1]
[1,2,1,2,3,3,2,3,1]
[1,2,1,2,3,3,2,1,3]
[1,2,1,2,3,2,3,3,1]
[1,2,1,2,3,2,3,1,3]
[1,2,1,2,2,3,3,3,1]
[1,2,3,1,3,2,3,1,2]
[1,2,3,1,3,2,1,2,3]
[1,2,3,1,2,3,3,1,2]
[1,2,3,1,2,3,1,3,2]
[1,2,3,1,2,3,1,2,3]
[1,2,1,3,3,3,2,1,2]
[1,2,1,3,3,2,3,1,2]
[1,2,1,3,3,2,1,3,2]
[1,2,1,3,3,2,1,2,3]
[1,2,1,3,2,3,3,1,2]
[1,2,1,3,2,3,1,3,2]
[1,2,1,3,2,3,1,2,3]
[1,2,1,3,2,1,3,3,2]
[1,2,1,3,2,1,3,2,3]
[1,2,1,2,3,3,3,1,2]
[1,2,1,2,3,3,1,3,2]
[1,2,1,2,3,3,1,2,3]
[1,2,1,2,3,1,3,3,2]
[1,2,1,2,3,1,3,2,3]
[1,2,1,2,1,3,3,3,2]
[1,2,1,3,3,1,2,2,3]
[1,2,1,3,1,3,2,2,3]
[1,2,1,3,1,2,3,3,2]
[1,2,1,1,3,3,2,3,2]
[1,2,1,1,3,3,2,2,3]
[1,2,1,1,3,2,3,3,2]
[1,2,1,1,3,2,3,2,3]
[1,2,1,1,2,3,3,3,2]
[1,2,1,1,2,3,3,2,3]
[1,1,2,3,3,3,2,2,1]
[1,1,2,3,3,2,3,2,1]
[1,1,2,3,3,2,2,3,1]
[1,1,2,3,3,2,2,1,3]
[1,1,2,3,2,3,3,2,1]
[1,1,2,3,2,3,2,3,1]
[1,1,2,3,2,3,2,1,3]
[1,1,2,3,2,2,3,3,1]
[1,1,2,3,2,2,3,1,3]
[1,1,2,3,2,2,1,3,3]
[1,1,2,2,3,3,3,2,1]
[1,1,2,2,3,3,2,3,1]
[1,1,2,2,3,3,2,1,3]
[1,1,2,2,3,2,3,3,1]
[1,1,2,2,3,2,3,1,3]
[1,1,2,2,3,2,1,3,3]
[1,1,2,2,2,3,3,3,1]
[1,1,2,2,2,3,3,1,3]
[1,1,2,3,3,3,2,1,2]
[1,1,2,3,3,2,3,1,2]
[1,1,2,3,3,2,1,3,2]
[1,1,2,3,3,2,1,2,3]
[1,1,2,3,2,3,3,1,2]
[1,1,2,3,2,3,1,3,2]
[1,1,2,3,2,3,1,2,3]
[1,1,2,3,2,1,3,3,2]
[1,1,2,3,2,1,3,2,3]
[1,1,2,3,2,1,2,3,3]
[1,1,2,2,3,3,3,1,2]
[1,1,2,2,3,3,1,3,2]
[1,1,2,2,3,3,1,2,3]
[1,1,2,2,3,1,3,3,2]
[1,1,2,2,3,1,3,2,3]
[1,1,2,2,3,1,2,3,3]
[1,1,2,2,1,3,3,3,2]
[1,1,2,2,1,3,3,2,3]
[1,1,2,3,3,3,1,2,2]
[1,1,2,3,3,1,2,3,2]
[1,1,2,3,3,1,2,2,3]
[1,1,2,3,1,3,2,3,2]
[1,1,2,3,1,3,2,2,3]
[1,1,2,3,1,2,3,3,2]
[1,1,2,3,1,2,3,2,3]
[1,1,2,1,3,3,3,2,2]
[1,1,2,1,3,3,2,3,2]
[1,1,2,1,3,3,2,2,3]
[1,1,2,1,3,2,3,3,2]
[1,1,2,1,3,2,3,2,3]
[1,1,2,1,3,2,2,3,3]
[1,1,2,1,2,3,3,3,2]
[1,1,2,1,2,3,3,2,3]
[1,1,2,1,2,3,2,3,3]
[1,1,1,2,3,3,3,2,2]
[1,1,1,2,3,3,2,3,2]
[1,1,1,2,3,3,2,2,3]
[1,1,1,2,3,2,3,3,2]
[1,1,1,2,3,2,3,2,3]
[1,1,1,2,3,2,2,3,3]
[1,1,1,2,2,3,3,3,2]
[1,1,1,2,2,3,3,2,3]
[1,1,1,2,2,3,2,3,3]
[1,1,1,2,2,2,3,3,3]

 
 
 
 
 
 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值