順列生成(一般順列)問題(2)の考察1を示します。
問題(2)の考察1
選択法で辞書式順序に順列を生成する方法を使って、一般順列を生成する。
' << GP211.bas >> ' 考察2に基づく一般順列生成プログラム。 ' Tiny Basic ' Public A(99): ' 集合{1,2,...,r}上の順列を保存する配列。 Public B(99): ' B(i):要素i(1≦i≦n)の個数。 Public C(99): ' C(g)はグループ番号gに含まれる要素が昇順に ' 出現しているかどうか監視する。 ' 出現するたびに1つ増加する。 Public G(99): ' 要素i(1≦i≦r)が属するグループ番号G(i)。 Public N: ' 集合の要素数。 Public R: ' 一般順列の長さ。 Public COUNT ' 一般順列の個数。 ' Do ' 要素数nの読み込み。 Read N If (N <= 0) or (N > 99) Then Exit Do ' ' 各要素の個数の入力。 B(0)=0 For I=1 To N: Read B(I): Next I ' Data 2, 2,2 Data 3, 2,2,1 Data 0 ' ' 一般順列の長さの計算。 R=0 For I=1 To N: R=R+B(I): Next I If R > 99 Then Stop ' ' 配列Gの初期設定。 ' {1,2,…,r}上の順列の各要素にグループ番号を割り当てる。 K=0 For I=1 To N For J=1 To B(I): K=K+1: G(K)=I: Next J Next I ' ' 配列Cの初期設定。 ' グループ内で昇順を保証する配列の初期設定。 C(1)=1 For I=2 To N: C(I)=C(I-1)+B(I-1): Next I ' ' 配列Aの初期設定。 For I=0 To R: A(I)=I: Next I COUNT=0 ' ' 一般順列の生成。 Call Perm(0) ' ' 実行結果。 Print Using"集合の要素数###";N For I=1 To N Print Using"要素## 個数##";I;B(I) Next I Print "一般順列の個数:";COUNT Print Loop End ' ' 一般順列を生成する再帰手続き。 Sub Perm(K) If K = R Then ' 一般順列の出力。 COUNT=COUNT+1 Print Using"#####: ";COUNT; For I=1 To R: Print Using"##";G(A(I));: Next I Print Exit Sub End If ' ' 深さKの節点から深さK+1の子節点をN-K個作成する。 For I=K+1 To R ' I番目とK+1番目の要素を交換する。 W=A(K+1): A(K+1)=A(I): A(I)=W ' グループ内で昇順が確認された場合、深さK+1の子節点に進む。 If C(G(A(K+1))) = A(K+1) Then C(G(A(K+1)))=C(G(A(K+1)))+1 ' 深さK+1の子節点を作成する。 Call Perm(K+1) C(G(A(K+1)))=C(G(A(K+1)))-1 End If Next I ' 交換を戻す。 T=A(K+1) For J=K+2 To R: A(J-1)=A(J): Next J A(R)=T End Sub