|
> No.1363[元記事へ]
眞里さんへのお返事です。
!全スキャンするだけの、ツールです。
!9個 でも 最長部分列の長さが、4に満たないものが、1764 個あります。
!10個 で、全て4以上になります。3,682,800 通りですが、大して時間は
!かかりません。(Pen.3-500M でも10 分程)
! ~85696: 3 2 1 7 6 9 8 4 5 |増=(3) 3 7 9 |減=(3) 3 2 1
!~281644: 7 8 9 2 1 5 6 3 4 |増=(3) 7 8 9 |減=(3) 7 2 1
!~281996: 7 8 9 4 5 6 1 2 3 |増=(3) 7 8 9 |減=(3) 7 4 1
!最長増加部分列 Longest Increasing Subsequence の求め方については、
!----------------------------------------------
!<< 実験 >>
OPTION ARITHMETIC NATIVE
LET ss=1 !配列内、数列データーの始め( ss は、2 以上、0 以下でもよい)
LET mm=9 !配列内、数列データーの終り
LET rr=4 ! 最長部分列の、長さの下限
!
DIM n0(ss-1 TO mm),nn(ss-1 TO mm), L(ss-1 TO mm),P1(ss-1 TO mm),P2(ss-1 TO mm)
!
FOR i=ss TO mm
LET n0(i)=i
NEXT i
LET t00=TIME
CALL perm(n0,ss)
PRINT "perm.number=";num
PRINT "検査された数列の数=";num
PRINT "表示された数列の数=";num2
LET i=TIME-t00
IF i< 0 THEN LET i=i+86400
PRINT TRUNCATE(i,2);"秒 終了 ";
SUB perm(n0(),j) !n0( ss)~n0( mm) の順列組合せを、nn( ss)~nn( mm) に作る。
local i
IF j<=mm THEN
FOR i=ss TO ss+mm-j
LET nn(j)=n0(i)
swap n0(i),n0(ss+mm-j)
CALL perm(n0,j+1)
swap n0(i),n0(ss+mm-j)
NEXT i
ELSE
!----- !nn()= 全ての順列を、連射する。
LET num=num+1
IF MOD(num,10000)=0 THEN PRINT "perm.number=";num
CALL check
!! CALL check_all !テスト用、全ての表示。
END IF
END SUB
SUB check
CALL LIS !最長増加部分列の長さ inc を 求める。
IF inc< rr THEN CALL LDS !rr 未満ならば 最長減少部分列の長さ dec も 求める。
IF inc< rr AND dec< rr THEN CALL print1 !昇・降とも 下限(rr)未満のみを、表示。
END SUB
SUB check_all
CALL LIS !最長増加部分列の長さ inc を 求める。
CALL LDS !最長減少部分列の長さ dec を 求める。
CALL print1 !全て表示。
END SUB
!----------------
SUB LIS !Longest Increasing Subsequence
LET inc=0
LET L(ss-1)=0
FOR i=ss TO mm
LET k=ss-1
FOR j=ss TO i-1
IF nn(j)< nn(i) AND L(k)< L(j) THEN LET k=j
NEXT j
LET L(i)=L(k)+1
LET P1(i)=k
!---
IF inc< L(i) THEN
LET inc=L(i)
LET ini=i
END IF
NEXT i
END SUB
!----------------
SUB LDS !Longest Decreasing Subsequence
LET dec=0
LET L(ss-1)=0
FOR i=ss TO mm
LET k=ss-1
FOR j=ss TO i-1
IF nn(j)> nn(i) AND L(k)< L(j) THEN LET k=j
NEXT j
LET L(i)=L(k)+1
LET P2(i)=k
!---
IF dec< L(i) THEN
LET dec=L(i)
LET dei=i
END IF
NEXT i
END SUB
!----------------
SUB strLIS(i)
IF i< ss THEN EXIT SUB
CALL strLIS(P1(i))
LET w$=w$& USING$("###",nn(i))
END SUB
SUB strLDS(i)
IF i< ss THEN EXIT SUB
CALL strLDS(P2(i))
LET w$=w$& USING$("###",nn(i))
END SUB
!----------------
SUB print1
LET num2=num2+1
LET w$=STR$(num)& ": "
FOR i=ss TO mm
LET w$=w$& USING$("###",nn(i))
NEXT i
LET w$=w$& " |増=("& STR$(inc)& ")"
CALL strLIS(ini)
LET w$=w$& " |減=("& STR$(dec)& ")"
CALL strLDS(dei)
PRINT w$
END SUB
END
|
|