Лекции по СЯП (987656), страница 2
Текст из файла (страница 2)
s7
Рис.3
На рис.3 показана последовательность ситуаций, определяющей кратчайшее решение игры. Каждую из ситуаций можно представить тройкой. Например, начальную ситуацию s0 можно представить тройкой (123,ε,ε), а ситуации s5 и s6 – тройками (1,3,2) и (1,23,ε). (Здесь ε обозначает пустое слово.)
В общем случае, когда имеется n дисков, произвольная возможная ситуация в игре, может быть описана тройкой вида
(i1i2…ip, j1j2…jq, k1k2…kr),
где i1, i2,…, ip – номера дисков, находящихся на первом колышке, j1, j2,…, jp – номера дисков, находящихся на втором колышке, k1, k2,…,kp – номера дисков, находящиеся на третьем колышке. Мы здесь предполагаем, что диски пронумерованы в порядке их размера и i1<i2<…< ip, j1< j2<…< jp, k1<k2<…<kp. (Заметим, что {i1, i2,…, ip} {j1, j2,…, jp}
{k1, k2,…,kp} и эти множества попарно не пересекаются.)
Таким образом, кратчайшее решение игры с тремя дисками вместе с ситуациями, возникающими в процессе игры, можно формально описать так:
(123,ε,ε) <1 2> (23,1,ε) <1
3> (3,1,2) <2
3> (3,ε,12) <1
2>
(ε,3,12) <3 1> (1,3,2) <3
2> (1,23,ε) <1
2> (ε,123,ε)
(1,ε,ε)
(ε,ε,1) (ε,1,ε)
(12,ε,ε)
(2,1,ε) (2,ε,1)
(ε,1,2) (ε,2,1)
(ε,ε,12) (ε,12,ε)
(1,ε,2) (1,2,ε)
(123,ε,ε)
(23,1,ε)
(3,1,2)
(3,ε,12)
(ε,3,12)
(1,3,2)
(1,23,ε)
(ε,123,)
Рис.4
Обозначим через h(n,i,j) решение задачи, т.е. кратчайшую последовательность шагов от состояния (12…n, ε, ε) к состоянию (ε, ε ,12…n). Каждый ход представляется парой вида <i j>, которая указывает, что нужно перенести диск с колышка номер i на колышек номер j. Таким образом, последовательность шагов представляется словом в алфавите
{<1 2>, <1
3>, <2
1>, <2
3>, <3
1>, <3
2>}.
Решение задачи для трех дисков представляется словом
h(3,1,2) = <1 2> <1
3> <2
3> <1
2> <3
1> <3
1> <1
2>
Ясно, что
h(n,1,2) = h(n–1,1,3) <1 2> h(n–1,3,2).
Вообще, для произвольных i, j (i j)
h(n,i,j) = h(n–1, i, t(i,j)) <i j> h(n–1, t(i,j) ,j)
Таким образом, имеем следующую рекурсивную программу:
R: h(n,1,2) <= h(n–1,1,3) <1 2> h(n–1,3,2)
h(n,1,3) <= h(n–1,1,2) <1 3> h(n–1,2,3)
h(n,2,1) <= h(n–1,2,3) <2 1> h(n–1,3,1)
h(n,2,3) <= h(n–1,2,1) <2 3> h(n–1,1,3)
h(n,3,1) <= h(n–1,3,2) <3 1> h(n–1,2,1)
h(n,3,2) <= h(n–1,3,1) <3 2> h(n–1,1,2)
Пример. Применим эту программу для того, чтобы решить задачу «Ханойская башня» для трех дисков.
h(3,1,2) (1)
h(2–1,1,2)<1 3>h(2–1,2,3)<1
2>h(2–1,2,1)<2
3>h(2–1,1,3) (4)
h(1,1,2)<1 3>h(1,2,3)<1
2>h(1,2,1)<2
3>h(1,1,3) (5)
<1 2><1
3><2
3><1
2><2
1><2
3><1
3> (6)
Оценка вычислительной сложности программы R.
Операции программы: <= (подстановка), –1 (вычитание единицы).
Функция tR((n,1,2)) – число операций, выполненной программой R при ее применении к ситуации (n,1,2). Рассматривая протокол вычисления программы R для указанного примера, мы замечаем, что выполняются:
▪ 1 операция «<= » при переходе от (1) к (2);
▪ 2 операции «–1» при переходе от (2) к (3);
▪ 2 операции «<= » при переходе от (3) к (4);
▪ 4 операции «–1» при переходе от (4) к (5);
▪ 4 операции «<= » при переходе от (5) к (6).
Таким образом,
tR((3,1,2)) = 1+2+2+4+4 = 9.
Рассмотрим теперь протокол вычисления для входа (4,1,2).
h(4,1,2) (1)
h(3–1,1,2)<1 3>h(3–1,2,3)<1
2>h(3–1,2,1)<2
3>h(3–1,1,3) (4)
h(2,1,2)<1 3>h(2,2,3)<1
2>h(2,2,1)<2
3>h(2,1,3) (5)
h(2–1,1,3)<1 2>h(2–1,3,2)<1
3>h(2–1,2,1)<2
3>h(2–1,1,3)
<1 2>h(2–1,2,3)<2
1>h(2–1,3,1)<2
3>h(2–1,1,2)
h(1,1,3) <1 2>h(1,3,2)<1
3>h(1,2,1)<2
3>h(1,1,3)
<1 2>h(1,2,3)<2
1>h(1,3,1)<2
3>h(1,1,2)
<1 3><1
2><3
2><1
3><2
1><2
3><1
3><1
2>
<2 3><2
1><3
1><2
3><1
2><1
3><2
3> (8)
Так же, как и раньше, замечаем, что выполняются:
▪ 1 операция «<= » при переходе от (1) к (2);
▪ 2 операции «–1» при переходе от (2) к (3);
▪ 2 операции «<= » при переходе от (3) к (4);
▪ 4 операции «–1» при переходе от (4) к (5);
▪ 4 операции «<= » при переходе от (5) к (6);
▪ 8 операций «–1» при переходе от (6) к (7);
▪ 8 операций «<= » при переходе от (7) к (8).
Легко видеть, что протокол вычислений для входа (n,1,2) характеризуется следующим:
▪ число состояний в протоколе равно 2n ;
▪ при последовательных переходах выполняются следующие количества операций: 1, 2, 2, 4, 4, 8, 8,…, 2n–1, 2n–1 ;
▪ общее количество операций равно
1+2+2+4+4+8+8+…+2n+2n =1+ Σ 2k+1 = 2n+1.
Таким образом,
tR((n,1,2)) = 2n+1.
Вычисление чисел Фибоначчи
F1: f(n) <= f(n –1)+ f(n –2)
f(1) <= 1
f(2) <= 1
Вычислим f(9):
f(9)
f(9 –1)+ f(9 –2) 1 операции «<= »
f(8)+ f(7) 2 операции «– »
f(8 –1)+ f(8 –2)+ f(7 –1)+ f(7 –2) 2 операции «<= »
f(7)+ f(6)+ f(6)+ f(5) 4 операции «– »
f(7 –1)+ f(7 –2)+ f(6 –1)+ f(6 –2)+
f(6 –1)+ f(6 –2)+ f(5 –1)+ f(5 –2) 4 операций «<= »
f(6)+ f(5)+ f(5)+ f(4)+ f(5)+ f(4)+f(4)+ f(3) 8 операций «– »
f(6 –1)+ f(6 –2)+ f(5 –1)+ f(5 –2)+ f(5 –1)+ f(5 –2)+
f(4 –1)+ f(4 –2)+ f(5 –1)+ f (5 –2)+ f(4 –1)+ f(4 –2)+
f(4–1)+ f(4–2) )+ f(3 –1)+ f(3 –2) 8 операций «<= »
f(5)+ f(4)+ f(4)+ f(3)+ f(4)+ f(3)+ f(3)+ f(2)+
f(4)+ f(3)+ f(3)+ f(2)+ f(3)+ f(2)+ f(2)+ f(1) 16 операций «– »
f(5 –1)+ f(5 –2)+ f(4 –1)+ f(4 –2)+ f(4 –1)+ f(4 –2)+
f(3 –1)+ f(3 –2)+ f(4 –1)+ f(4 –2)+ f(3 –1) + f(3 –2)+
f(3 –1)+ f(3 –2)+ f(2 –1)+ f(2 –2)+ f(4 –1)+ f(4 –2)+
f(3 –1)+ f(3 –2)+ f(3 –1)+ f(3 –2)+ f(2 –1)+ f(2 –2)+
f(3 –1)+ f(3 –2)+ f(2 –1)+ f(2 –2)+ f(2 –1)+ f(2 –2)+ 1
16 операций «<= »
f(4)+ f(3)+ f(3)+ f(2)+ f(3)+ f(2)+ f(2)+ f(1)+ f(3)+ f(2)+
f(2) + f(1)+ f(2)+ f(1)+ f(1)+ f(0)+ f(3)+ f(2)+ f(2)+ f(1) +
f(2)+ f(1)+ f(1)+ f(0)+ f(2)+ f(1)+ f(1)+ f(0)+ f(1)+ f(0)+ 1
31 операция «– »
f(4 –1) + f(4 –2)+ f(3 –1)+ f(3 –2)+ f(3 –1)+ f(3 –2)+
f(2 –1)+ f(2 –2)+ f(3 –1)+ f(3 –2)+ f(2 –1)+ f(2 –2)+
f(2 –1)+ f(2 –2)+ 1+ f(3 –1)+ f(3 –2)+ f(2 –1)+ f(2 –2)+
f(2 –1)+ f(2 –2)+ 1+ f(2 –1)+ f(2 –2)+ 1+ 1+ 1+
f(3 –1)+ f(3 –2)+ f(2 –1)+ f(2 –2)+ f(2 –1)+ f(2 –2)+
1+ f(2 –1)+ f(2 –2)+ 1+ 1+ 1+ f(2 –1)+ f(2 –2)+
1+ 1+ 1+ 1+ 1+ 1 30 операций «<= »
f(3)+ f(2)+ f(2)+ f(1)+ f(2)+ f(1)+ f(1)+ f(0)+ f(2)+ f(1)+
f(1)+ f(0)+ f(1)+ f(0)+ f(2)+ f(1)+ f(1)+ f(0)+
f(1)+ f(0)+ f(1)+ f(0)+ f(2)+ f(1)+ f(1)+ f(0)+
f(1)+ f(0)+ f(1)+ f(0)+ f(1)+ f(0)+15 30 операций «– » и
14 операций «+ »
f(3 –1)+ f(3 –2)+ f(2 –1)+ f(2 –2)+ f(2 –1)+ f(2 –2)+ 1+
f(2 –1)+ f(2 –2)+ 1+ 1+ 1+ f(2 –1)+ f(2 –2)+ 1+ 1+
1+ 1+ 1+ f(2 –1)+ f(2 –2) + 1+ 1+ 1+ 1+ 1+1+1+
f(2 –1)+ f(2 –2)+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+15
32 операций «<= »
f(2)+ f(1)+ f(1)+ f(0)+ f(1)+ f(0)+ f(1)+ f(0)+ f(1)+ f(0)+ f(1)+
f(0)+ f(1)+ f(0)+ 36 14 операций «– » и
18 операций «+ »
f(2 –1)+ f(2 –2)+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+
1+ 1+ 1+ 36 14 операций «<= »
f(1)+ f(0)+ 49 2 операции «–» и
13 операций «+ »
1+ 1 + 49 2 операции «<= »
51 2 операции «+ »
65
tF1(n) = O(2n)
Итеративный алгоритм для вычисления чисел Фибоначчи
F2: Y := 1; Z := 1; V := |_ X /2_| ;
while V = 1 do Y := Y+Z ; Z := Y+Z ; V := V – 1 od;
if X mod 2 = 0 then return Y else Y+Z.
Здесь X – входная переменная, Y – выходная переменная, Z, V – рабочие переменные.
Вычислим для входов X = 8 и Х =7.
X = 8 X = 7
---------------- ---------------
X Y Z V X Y Z V
8 0 0 0 7 0 0 0
8 1 0 0 7 1 0 0
8 1 1 0 7 1 1 0
8 1 1 4 7 1 1 3
8 2 1 4 7 2 1 3
8 2 3 4 7 2 3 3
8 2 3 3 7 2 3 2
8 5 3 3 7 5 3 2
8 5 8 3 7 5 8 2
8 13 8 2 7 5 8 1
8 13 21 2 ---------------
8 34 21 2 Y = 21
8 34 55 1
__________
Y = 34
0 1 2 3 4 5 6 7 8
1 1 2 3 5 8 13 21 34
tF2(n) = 3n+1
tF2(n) = O(n)
1.3. Простейший язык программирования L
Синтаксис языка L
Синтаксические классы:
Var – переменные,
Num – нумералы (десятичные представления натуральных чисел),
Int – нумералы или нумералы со знаком минус,
Aexp – арифметические выражения,
Bexp – булевы выражения,
Stm – операторы (предложения),
Prog – программы.