7.3.1. Написать программу, которая печатает по одному разу все
последовательности длины n, составленные из чисел
(их количество равно ).
procedure generate; | var i,j : integer; begin | if t = n then begin | | for i:=1 to n do begin | | | write(a[i]); | | end; | | writeln; | end else begin {t < n} | | for j:=1 to k do begin | | | t:=t+1; | | | a[t]:=j; | | | generate; | | | t:=t-1; | | end; | end; end;Основная программа теперь состоит из двух операторов:
t:=0; generate;`
Замечание. Команды t:=t+1 и t:=t-1 для экономии можно вынести из цикла for.
7.3.2. Написать программу, которая печатала бы все перестановки
чисел по одному разу.
for i:=1 to n do begin a[i]:=i; end; t:=0; generate;Вот описание процедуры:
procedure generate; | var i,j : integer; begin | if t = n then begin | | for i:=1 to n do begin | | | write(a[i]); | | end; | | writeln; | end else begin {t < n} | | for j:=t+1 to n do begin | | | поменять местами a[t+1] и a[j] | | | t:=t+1; | | | generate; | | | t:=t-1; | | | поменять местами a[t+1] и a[j] | | end; | end; end;`
7.3.3. Напечатать все возрастающие последовательности длины k,
элементами которых являются натуральные числа от 1 до n.
(Предполагается, что , иначе таких
последовательностей не существует.)
procedure generate; | var i: integer; begin | if t = k then begin | | печатать a[1]..a[k] | end else begin | | t:=t+1; | | for i:=a[t-1]+1 to t-k+n do begin | | | a[t]:=i; | | | generate; | | end; | | t:=t-1; | end; end;`Замечание. Цикл for мог бы иметь верхней границей n (вместо ). Наш вариант экономит часть работы, учитывая тот факт, что предпоследний (-ый) член не может превосходить , -ой член не может превосходить и т. п.
Основная программа теперь выглядит так:
t:=1; for j:=1 to 1-k+n do begin | a[1]:=j; | generate; end;Можно было бы добавить к массиву a слева фиктивный элемент , положить и ограничиться единственным вызовом процедуры generate.
7.3.4. Перечислить все представления положительного целого числа
n в виде суммы последовательности невозрастающих целых
положительных слагаемых.
procedure generate; | var i: integer; begin | if s = n then begin | | печатать последовательность a[1]..a[t] | end else begin | | for i:=1 to min(a[t], n-s) do begin | | | t:=t+1; | | | a[t]:=i; | | | s:=s+i; | | | generate; | | | s:=s-i; | | | t:=t-1; | | end; | end; end;Основная программа при этом может быть такой:
t:=1; for j:=1 to n do begin | a[1]:=j | s:=j; | generate; end;`
Замечание. Можно немного сэкономить, вынеся операции увеличения и уменьшения из цикла, а также не возвращая s каждый раз к исходному значению (увеличивая его на 1 и возвращая к исходному значению в конце). Кроме того, добавив фиктивный элемент , можно упростить основную программу:
t:=0; s:=0; a[0]:=n; generate;
7.3.5. Написать рекурсивную программу обхода дерева (используя те
же команды и проверки, что и в главе про обход дерева).
обработать_над
обрабатывает все
листья над текущей вершиной и заканчивает работу в той же
вершине, что и начала. Вот ее рекурсивное описание:
procedure обработать_над; begin | if есть_сверху then begin | | вверх_налево; | | обработать_над; | | while есть_справа do begin | | | вправо; | | | обработать_над; | | end; | | вниз; | end else begin | | обработать; | end; end;`