順列生成(一般順列)問題(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