{+----------------------------------------------------------------------+
 |            Urci kolika zpusoby lze zkonstruovat klic                 |
 +----------------------------------------------------------------------+}
 

PROGRAM Klic;
VAR nzubu,nurov,msous:BYTE;

{Vraci vetsi ze dvou cisel}
FUNCTION Max(a,b:BYTE):BYTE;
BEGIN
  IF (a>b) THEN Max:=a
           ELSE Max:=b;
END;

{Vraci mensi ze dvou cisel}
FUNCTION Min(a,b:BYTE):BYTE;
BEGIN
  IF (a<b) THEN Min:=a
           ELSE Min:=b;
END;

{Hledani poctu klicu rekurzi}
FUNCTION Klic1(nz,nu,ms:BYTE):LONGINT;
 FUNCTION Sum(ia,ib,nn:BYTE):LONGINT; FORWARD;
 FUNCTION Kl(u,n:BYTE):LONGINT;
 BEGIN
  IF (n=nz) THEN
    Kl:=1
  ELSE
    Kl:=Sum(MAX(1,u-ms),MIN(nu,u+ms),n+1)
 END;
 FUNCTION Sum(ia,ib,nn:BYTE):LONGINT;
 VAR i:BYTE; hlp:LONGINT;
 BEGIN
  hlp:=0;
  FOR i:=ia TO ib DO hlp:=hlp+Kl(i,nn);
  Sum:=hlp
 END;
BEGIN
 Klic1:=Sum(1,nu,1)
END;

{Prime hledani tabulkou}
FUNCTION Klic2(nz,nu,ms:BYTE):LONGINT;
 VAR a:ARRAY[1..20,1..50] OF LONGINT;
     i,j,k: BYTE;
     hlp:LONGINT;
BEGIN
 FOR i:=1 TO nu DO a[1,i]:=1;
 FOR i:=2 TO nz DO
   FOR j:=1 TO nu DO BEGIN
     a[i,j]:=0;
     FOR k:=MAX(1,j-ms) TO MIN(nu,j+ms) DO
       a[i,j]:=a[i,j]+a[i-1,k]
   END;
 hlp:=0;
 FOR j:=1 TO nu DO hlp:=hlp+a[nz,j];
 klic2:=hlp
END;

BEGIN
  WRITELN('VLOZTE PARAMETRY KLICE:');
  WRITE('Pocet zubu:'); READLN(nzubu);
  WRITE('Pocet urovni:'); READLN(nurov);
  WRITE('Max. rozdil urovni sousednich zubu:'); READLN(msous);
  WRITELN('Rekuzivni klic:  ',Klic1(nzubu,nurov,msous));
  WRITELN('Nerekuzivni klic:  ',Klic2(nzubu,nurov,msous));
  READLN;
  WRITELN('=======================END=========================');
END.