Kawazoe(@riverplus)さんのCodeIQの問題です。
問題はこちらのお世話になりました。解答もあります。
->https://sw-logic.com/Portfolio/Programing/CodeIQ/3314.php
こちらに関連の情報があります。
->https://togetter.com/li/1125965
テストケースはあちこちからかき集めたような気がします。
左下から右上に上がる斜線ごとに右端から積み上げます。
ある線上の数<=右隣の線上の数+1となります。
ある状態から①と②の両方を試みる事を繰り返します。
①残りの丸太の数をc、左端の数をnとするとc-nとn+1の小さい方を左に並べる
②左端の丸太を一つ除く
最後に①の場合の数と②の場合の数を足します。
prologでかきました。
functor/3とtwoar/3を使って二次元配列を作りメモ化します。
キーはcとn、値はその時点までの場合の数です。
%:-initialization(start). %ideone
%start.
twoar(F,0,_). % 二次元配列、メモ化に使用
twoar(F,X,Y):-arg(X,F,V),functor(V,z,Y),X1 is X-1,twoar(F,X1,Y).
data(F,X,Y,V):-arg(X,F,V1),arg(Y,V1,V). %データの入出力
tum1(0,_,_,1):-!.
tum1(_,0,_,0):-!.
tum1(C,N,F,R):-
data(F,C,N,R),nonvar(R),!.
tum1(C,N,F,R):-
C1 is C-N,M is min(C1,N+1),tum1(C1,M,F,R2),N2 is N-1,
tum1(C,N2,F,R3),R is R2+R3,data(F,C,N,R).
solve(C,B):-
functor(F,x,C),N1 is integer(sqrt(C*2)),twoar(F,C,N1),
(tum1(C,1,F,R)->(R=:=B->Str=" ok ";Str=" no "); write(fail)),
write(" "),write(Str),writeln(R),!.
start:-f(C,B),solve(C,B),fail.
f(1,1).
f(3,2).
f(4,3).
f(5,5).
f(10,78).
f(11,135).
f(60,72875530905117).