|
> No.3770[元記事へ]
GAIさんへのお返事です。
> 6行10列の行列で
> 各成分は0か1が入っており
> 各行は同数の0,1が含まれ(即ち0が5個、1が5個ずつある。)
> 各列にも同数の0,1がある。(即ち0が3個、1が3個ずつある。)
> そして
> どの2つの行をくらべても1が含まれている位置が2カ所で等しくなっている。
たくさんあります。
得られた結果の行、列を入れ替えたものも解です。
1の重なり具合が行数の(半分-1)なら、縦方向(列)の確認はなくてもよさそうです。(赤色部分)
LET N=10
LET Y=6
!!LET N=14
!!LET Y=8
PUBLIC NUMERIC C !場合の数
LET C=0
DIM M(Y) !ビットパターン
FOR H=0 TO COMB(N,N/2)-1 !1行目
LET M(1)=Num2CombBit(H,N,N/2) !1行目
CALL try(2,M,N,Y)
NEXT H
PRINT C;"通り"
END
EXTERNAL SUB try(P,M(),N,Y)
FOR H=0 TO COMB(N,N/2)-1 !p行目の候補
LET T=Num2CombBit(H,N,N/2)
IF T>M(P-1) THEN !対称性
FOR K=1 TO P-1 !前出パターンとの比較
LET W=BITAND(M(K),T)
LET X=0 !1の個数
DO WHILE W>0
LET X=X+MOD(W,2)
LET W=INT(W/2)
LOOP
IF X<>2 THEN EXIT FOR !2以外はNG
!!IF X<>3 THEN EXIT FOR !3以外はNG
NEXT K
IF K>P-1 THEN !OKなら
LET M(P)=T
IF P=Y THEN !すべて埋まったなら
MAT PRINT M; !debug
DIM F(N) !縦方向を確認する
MAT F=ZER
FOR K=1 TO P
LET W=M(K)
FOR B=1 TO N
IF W=0 THEN EXIT FOR
LET F(B)=F(B)+MOD(W,2)
LET W=INT(W/2)
NEXT B
NEXT K
FOR B=1 TO N
IF F(B)<>Y/2 THEN EXIT FOR
NEXT B
IF B>N THEN !OKなら
LET C=C+1
FOR K=1 TO Y !結果を表示する
PRINT RIGHT$(REPEAT$("0",N-1)&BSTR$(M(K),2),N)
NEXT K
END IF
ELSE
CALL try(P+1,M,N,Y) !次へ
END IF
END IF
END IF
NEXT H
END SUB
EXTERNAL FUNCTION Num2CombBit(h,N,R) !番号から組合せビットパターンを生成する ※辞書式順序
LET v=h+1
LET j=R
LET A=0
FOR i=N-1 TO 0 STEP -1 !組合せをビット位置とする
LET t=COMB(i,j)
IF v>t THEN
LET A=A+2^i !ビット位置(N-i-1)を1とする
LET j=j-1
LET v=v-t
END IF
NEXT i
LET Num2CombBit=A
END FUNCTION
実行結果
31 227 364 692 849 906
0000011111
0011100011
0101101100
1010110100
1101010001
1110001010
31 227 364 692 850 905
0000011111
0011100011
0101101100
1010110100
1101010010
1110001001
31 227 364 696 849 902
0000011111
0011100011
0101101100
1010111000
1101010001
1110000110
31 227 364 696 850 901
0000011111
0011100011
0101101100
1010111000
1101010010
1110000101
31 227 364 724 817 906
0000011111
0011100011
0101101100
1011010100
1100110001
1110001010
:
:
|
|