Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекция_6_new.doc
Скачиваний:
0
Добавлен:
01.03.2025
Размер:
126.98 Кб
Скачать

Задача о размещениях (факториал)

Например, приглашено n гостей. Необходимо рассадить их с учетом привязанностей, характеров и т.п. Сколько вариантов надо перебрать? То есть сколькими способами можно разместить гостей? Задача легко решается рекурсивно.

Пусть известно, что рассадить n-1 гостей можно F(n-1) способами. Куда можно посадить n-того гостя? Перед первым, перед вторым, . . . , перед последним и после последнего. Всего n вариантов. Тогда общее количество вариантов – F(n-1) = F(n)*n. А какая самая простая подзадача? – рассадить одного человека. Ее решение F(1) = 1.

Окончательное решение

F(n-1) = F(n)*n

F(1) = 1

Это всем известная формула для факториала n! = (n-1)!*n.

Решение задачи о размещения на Прологе методом общей рекурсии

predicates

fact(integer, integer)

clauses

fact(1, 1).

fact(N, P):-N1=N-1, fact(N1, P1), P=P1*N.

Предикат fact включает два аргумента. Первый аргумент – размер задачи (число гостей), второй – результат (число размещений). В Прологе первым всегда пишется предикат для решения простого случая. В данном случае при аргументе n=1, результат тоже равен единице. Второе правило состоит из трех подцелей. Первая – это уменьшение размерности задачи (к сожалению Пролог запрещает писать в качестве параметров предиката арифметические выражения). Вторая подцель – рекурсивное обращение с уменьшенным значением аргумента n. Третья подцель – формирование общего решения из только, что полученного.

Восходящая (хвостовая) рекурсия

Для вычисления факториала n!=1*2*3*…*n. начальное значение (обозначим его как R0=1) надо умножать на число I0=0 которое, увеличивается на 1 при каждом рекурсивном вызове. Когда значение I0 сравняется с n, рекурсивные вызовы заканчиваются.

Пример

f(N, R) :- fv(N, R, R0=1, I0=0). так писать нельзя (это для наглядности)

f(N, R) :- fv(N, R, 1, 0).

Водиться вспомогательная процедура с двумя дополнительными параметрами

R0=1 – начальное значение факториала

I0=0 - счетчик числа рекурсивных вызовов

fv(N, R, R0, I0):- I0 < N, - проверка на окончание

I1=I0+1, - модификация счетчика

R1=R0*I1, - вычисление текущего значения факториала

fv(N, R, R1, I1). - хвостовая рекурсия

После окончания рекурсивных вызовов в R1 будет последнее вычисленное значение факториала. Для пересылки его в переменную R используется следующая конструкция предиката.

fv (­_ , R, R, _ ).

Прологу предписывается проверить возможность равенства переменных R и R1. Это возможно, если присвоить свободной переменной R значение связанной переменной R1.

Задача о сумме натуральных чисел S = 1 + 2 + 3 + … + n.

Получим рекуррентную формулу для вычисления суммы. Для этого вычтем из Sn Sn-1

Sn = 1 +2 + . . . + (n-1) + n

Sn-1 = 1 + 2 + . . . + (n-1)

- - - - - - - - - - - - - - - - - - - - - -

Sn – Sn-1 = n

Sn = Sn-1 + n

S0 = 0

Программу на Прологе составить самостоятельно.

Общая

Хвостовая

Sum(0,0).

Sum(N,S): -

N1 = N –1,

Sum(N1,S1),

S = S1+N,

N1>=0.

Sum(N,S): - Sm(N,S,1,0).

Sm(N,S,N0,S0): -

N0 <= N,

N1=N0 + 1,

S1= N0 + S0,

Sm(N,S,N1,S1).

Sum(_,S,_,S).

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]