パズル万華鏡

面白いパズルの紹介と解説をします。

順列生成(多段順列)問題(7)の考察2

 順列生成(多段順列)問題(7)の考察2を示します。

問題(7)の考察2
f:id:isemba:20200511192249p:plain
f:id:isemba:20200511192304p:plain

' << MC111.bas >>
' 問題(7)の考察2に基づくプログラム
' Tiny Basic
'
Public P(10,10) ' m段r組合せを保存する配列。
Public N        ' n×nのチェス盤。
Public R        ' r個。 
Public COUNT    ' m段r組合せの個数。
Public COL(10)  ' 列jに置かれている駒数。
Public DOWN(18) ' 左上から右下方向の斜め線。
                ' マス目(i,j)を通る斜め線は、DOWN(i-j+n)
                ' マス目(i,j)に置かれている駒数。
Public UP(19)   ' 左下から右上方向の斜め線。
                ' マス目(i,j)を通る斜め線は、UP(i+j)
                ' マス目(i,j)に置かれている駒数。
'
Do
  ' N,Rの読み込み。
  Read N,R
  If (N <= 0) or (N > 10) Then Exit Do
  Data 6,2
  Data 0,0
  '
  ' 配列Pの初期設定。
  For I=1 To N
    For J=0 To N: P(I,J)=J: Next J
  Next I
  '
  ' 配列COLの初期設定。
  For J=1 To N: COL(J)=0: Next J
  '
  ' 配列UPの初期設定。
  For K=2 To 2*N: UP(K)=0: Next K
  '
  ' 配列DOWNの初期設定。
  For K=1 To 2*N-1: DOWN(K)=0: Next K
  '
  ' 初期設定。
  COUNT=0
  '
  ' m段r組合せ生成。
  Call Mperm(1,0)
  '
  ' 結果の出力
  Print Using"N=## R=##";N;R
  Print "COUNT=";COUNT
Loop
End
'
' D:段数 K:深さ
Sub Mperm(D,K)
  Dim CH$(10,10)
  If D > N Then             
    ' n段r組合せの表示。
    COUNT=COUNT+1
    Print "[";COUNT;"]"
    For I=1 To N
      For J=1 To N: CH$(I,J)="□": Next J
    Next I
    For I=1 To N
      For J=1 To R: CH$(I,P(I,J))="●": Next J
    Next I
    For I=1 To N
      For J=1 To N: Print CH$(I,J);: Next J
      Print
    Next I
    Exit Sub                               
  End If 
  '
  If K = R Then
    '次の段に進む。   
    Call Mperm(D+1,0)
  Else
    ' D段目の組合せ中、
    ' 深さKの節点から深さK+1の子節点 N-K個を生成する。
    For I=K+1 To N  
      T=P(D,I)
      '
      ' 各段の要素は昇順。降順の場合、次の要素に進む。
      If P(D,K) > T Then Goto *LAB
      '
      ' 縦,横,斜めで指定された駒数を超えている場合、次の要素に進む。 
      If COL(T) >= R Then Goto *LAB
      If UP(D+T) >= R Then Goto *LAB
      If DOWN(D-T+N) >= R Then Goto *LAB
'
      COL(T)=COL(T)+1
      UP(D+T)=UP(D+T)+1
      DOWN(D-T+N)=DOWN(D-T+N)+1
'
      ' I番目とK+1番目の要素を交換する。
      W=P(D,I): P(D,I)=P(D,K+1): P(D,K+1)=W
      ' 深さK+1の子節点を作成する。
      Call Mperm(D,K+1) 
      ' 交換を戻す。          
      W=P(D,I): P(D,I)=P(D,K+1): P(D,K+1)=W
'
      COL(T)=COL(T)-1
      UP(D+T)=UP(D+T)-1
      DOWN(D-T+N)=DOWN(D-T+N)-1
'
    *LAB:
    Next I
  End If
End Sub

f:id:isemba:20200511192411p:plain
f:id:isemba:20200511192424j:plain