Program Example_5;

Const n=10;

a: ar=(4, 2, -1, 5, 2, 9, 4, 8, 5, 3);

type ar=array[1..n] of integer;

Function min(a, b:integer):integer;

  begin

  if a>b then min:=b

  else min:=a;

  end;

Function P_min(n, b: integer):integer;

  begin

  if n=2 then P_min:=min(a[2], a[1])

  else P_min:=min(a[n], P_min(n-1, a[n]));

  end;

Begin

  writeln(‘минимальный элемент массива-‘, P_min(n, a[n])

End.

Задача 6 «Лабиринт»

Может ли путник выйти из лабиринта? Если может, то напечатать путь от выхода до начального положения путника.

Лабиринт задан массивом А размером 40х40, в котором:

А[k, m]=0, если клетка [k, m] «проходима»

А[k, m]=1, если клетка [k, m] «непроходима».

Начальное положение путника задаётся в проходимой клетке [i, j].  Путник может перемещаться из одной проходимой клетки в другую, если они имеют общую сторону. Путник выходит из лабиринта, когда попадает в граничную клетку (т. е. клетку [k, m], где k или  m равны 1 или 40.

Решение распадается на 2 части: поиск пути для выхода и печать обратного пути – от выхода до начального положения путника.

Простейшее решение первой части такое:

- Запишем в клетку  A[i, j], где вначале находится путник, число 2 и положим k=2.

- Просмотрим все клетки  А лабиринта. Для каждой из них, если в ней записан 0, прочтём четырех из её соседей. Если хоть в одной из соседних клеток записано число k (сейчас ещё равное 2), то в рассматриваемую клетку А впишем число k+1/

НЕ нашли? Не то? Что вы ищете?

- Теперь увеличим k:=k+1 и снова рассмотрим все клетки А. Этот процесс закончится когда-либо число будет вписано в граничную клетку ( выхода нет). Просмотров всего массива будет столько, сколько клеток окажется в кратчайшей дорожке.

Предыдущий алгоритм легко улучшить. На каждом шаге будем по-прежнему рассматривать все клетки А лабиринта. Если в клетке записан 0, а в какой-либо соседней находится число k>=2, то впишем в клетку А число k+1. Ясно, что это тоже решение задачи. Но если повезет, то здесь решение найдётся быстрее.

Заведомо эффективнее будет программа, которая начиная с исходной клетки, (куда вначале записывается число 2), ищет первого же свободного ( т. е. с числом 0) соседа. Вписывает в него 3 и ищет его свободного соседа, чтобы  вписать в него 4 и т. д.

Процесс прервется либо при достижении границы (выход найден), либо оттого, что свободных соседей не будет (тупик).

Если тупик возникает в соседней клетке (где записано число 2), то выхода нет. Если же тупиковая клетка иная и в неё вписано число k>2, то следует вписать в неё число 1 (сделать её непроходимой) и перейти к её соседней клетке с числом k-1. такая клетка есть и единственна.

!!! Программу для решения задачи о лабиринте можно сильно сократить. Если записать её рекурсивно.

Program labirint;

Const m=15;

  N=15;

Var i, j: integer;

  otvet: oolean;

  A: array [1..m, 1..n] of byte.

Procedure L (i, j: integer);

  begin

  if not( otvet) then

  if a[i, j]=0 then begin

  if (i=1) or (i=m) or (j=1) or (j=m) then otvet:=true;

  A[i, j]:=1; L(i, j-1); L(i, j+1); L(i-1, j); L(i+1, j);

  If otvet then writeln (i, ‘ ‘ ,j)

  end;

end;

Begin

For i:=1 to m do

For j:=1 to n do begin

Write(‘A[‘ , i, ’,’ ,j, ’]:=’);

Readln (a[i, j])

  end;

writeln;

writeln(‘i, j:=’);

readln(i, j);

writeln;

otvet:= false;

L(i, j);

If not( otvet) then writeln(‘нет выхода’)

End.

Задача 7 «Быстрая сортировка»

Реализация метода быстрой сортировки массива является прекрасным примером использования рекурсии. Этот метод был разработан в 1962 году профессором Оксфордского университета К. Хоаром.

Принцип метода:

Выбираем центральный элемент массива А и записываем его в переменную В. Затем элементы массива просматриваем  поочередно слева-направо  и справа-налево. При движении слева-направо ищем элемент А[i], который будет больше или равен В, и запоминаем его позицию. При движении справа-налево ищем элемент A[i], который будет меньше или равен В, и также запоминаем его позицию.

Найденные элементы меняем местами и т. д., пока при очередной итерации поиска встречные индексы i  и j не пересекутся.

  A  В=7  n=10 

  1  2  3  4  5  6  7  8  9  10

9

4

12

1

7

6

9

2

10

                                               

L=1  i=1                                                                  j=9  R=n

  9                                                                 2

  i=3         j=8        

  12  4

  i=5  j=6

  7  6

`

  5=j  i=6

  1  2  3  4  5  6  7  8  9  10 

2

4

4

1

6

7

8

12 

9

10

  <=В  >=В

После этого первый этап считается законченным, после чего элементы исходного массива окажутся разделёнными на 2 части относительно значения В – все элементы, которые <=В, будут располагаться слева от границы пересечения индексов i и j, а все элементы, которые >=В, будут располагаться справа от границы. Т. о., относительно значения В массив получается отсортированным, но левая и правая его части ещё не упорядочены.

2. На втором этапе повторяются действия первого этапа для левой и правой частей массива в отдельности. В результате массив окажется разбитым уже на 4 непересекающиеся по сортировке части, которые можно упорядочить по отдельности.

3. На 3 этапе повторяются действия первого этапа в отдельности для каждой из 4-х частей и т. д., пока длина сортируемых частей не станет равной одному элементу и, следовательно все элементы массива будут уже упорядочены.

Поскольку на каждом этапе повторяются одни и те же действия, но в разных индексных рамках массива, то их удобно оформить в виде самовызывающейся рекурсивной процедуры, которая используется в следующей программе:

Program QuickSort;

Uses Crt;

Const n=20;

Var A:array [1..n] of integer;

  i: word;

Procedure QSort (L, R: word);

Var B, x : integer;

  i, j: word;

begin

  B:=A[(L+R) div 2];

  i:=L;  j:=R;

  while i<=j do begin

  while A[i]<B do i:=i+1;

  while A[i]>B do j:=j-1;

  if i<=j then begin

  x:=A[i];

                                A[i]:=A[j];

                                A[j]:=x;

  i:=i+1;

                                j:=j-1

  end;

if L<R then QSort(L, j);

if i<R then QSort(i, R);

  end;

Begin

  ClrScr;

  Writeln(‘ ведите элементы массива’);

  For i:=1 to n do read (A[i]);

  Readln;

  QSort(1,n);

  Writeln (‘ Отсортированный массив:’);

  For i:=1 to n do write (A[i]:8);

End. 

­­

Задача 8

В написанном выражении ((((1?2)?3)?4)?5)?6)….?N  вместо каждого знака? вставить знак одной из четырёх операций: + - * / так, чтобы результат вычислений равнялся S (при делении дробная часть в частном отбрасывается). Найти все решения.

Обобщим задачу. Пусть требуется  так расставить знаки

  '+', '-', '*', '/' в выражении ((1?2)?3)...?N,

  чтобы в результате выполнения получилось значение S.

  Алгоритм.

  Конкретную расстановку знаков будем кодировать массивом

  c: array [0..(N-1)] of Integer

  ('+' -> 0,

  '-' -> 1,

  '*' -> 2,

  '/' -> 3).

  Чтобы сгенерировать все возможные комбинации знаков,

  требуется, фактически, построить все четверичные числа

  длины N-1. Будем строить их от 00..0 до 33..3. Элемент

  c[0] будет фиктивным и условие c[0] <> 0 сигнализирует

  об окончании генерации.

  Алгоритм генерации, по сути, есть последовательное

  увеличение на 1 четверичного числа, хранящегося в иве-

  ивее (см. действия с многозначными числами).

}

program Signs;

uses

  Crt;

const

  N = 6;

  S = 35;

var

  I, p: Integer;

  c: array [0..(N-1)] of Integer;

procedure WriteOneSign(Sgn: Integer);

begin

  case Sgn of

  0: Write(‘+’);

  1: Write(‘-‘);

  2: Write(‘*’);

  3: Write(‘/’);

  end;

end;

procedure OutputSigns;

var

  i: Integer;

begin

  for I := 1 to N-2 do

  Write(‘(‘);

  Write(‘1’);

  for I := 1 to N-2 do

  begin

  WriteOneSign(c[i]);

  Write(i+1, ‘)’);

  end;

  WriteOneSign(c[N-1]);

  Writeln(N, ‘=’, S);

end;

begin

  ClrScr;

Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5