Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Информатика / лекции

.pdf
Скачиваний:
24
Добавлен:
14.03.2016
Размер:
3.17 Mб
Скачать

4. Решение типовых задач на развилки и циклы

71

Тестовый пример может быть, скажем, таким:

вход: R =5 , x =3 , y = 4

выход: «точка лежит на окружности»

Далее рассмотрим модификацию предыдущей задачи, которую сформулируем следующим образом:

ПРИМЕР

Выяснить попадает ли точка с координатами (x, y) в заштрихованную

область (Рисунок 4.1 б)).

Для решения этой задачи нужно внимательно посмотреть на иллюстрацию и написать условия попадания точки в область круга радиуса R

Рисунок 4.3 Нерациональный алгоритм проверки попадания точки в заштрихованную область

72

4.1 Задачи на развилки

и в область расположенную над параболой. Условие попадания точки в круговую область: R2 > x2 + y2 . При решении задачи удобно пользоваться

переменными типа boolean, поскольку увеличивается наглядность алгоритма. Для круговой области мы воспользовались переменной L2, а для области над

параболой мы взяли переменную L1 и поместили в нее выражение y > a x2 .

Итак, если точка попадает в область над параболой, то выполнено условие L1, однако в этом случае точка не должна быть внутри круга, т.е. условие L2 должно быть равно FALSE. Ну а если условие L1 не выполняется, то для попадания точки в заштрихованную область необходимо чтобы она находилась внутри круга, т.е. чтобы L2 было равно TRUE. Описанные условия представлены в виде алгоритма на (Рисунок 4.3).

В качестве тестового примера можем записать такой набор входных и выходных данных:

входные: a =1, R =1, x = 0 , y = 0,5

выходные: «точка не попадает в область»

Далее идет листинг программы.

Program PRxor1; var x,y,R,a:real;

L1,L2:boolean; begin

writeLn('введите коэффициент a'); readLn(a);

writeLn('введите радиус R'); readLn(R);

writeLn('введите координаты x, y'); readLn(x,y);

L1:=y>a*sqr(x);

L2:=sqr(R)>sqrt(sqr(x)+sqr(y)); if L1 then

if L2 then

writeLn('точка не попадает') else

writeLn('точка попадает') else

if L2 then

writeLn('точка попадает') else

writeLn('точка не попадает');

end.

4. Решение типовых задач на развилки и циклы

73

Однако, задачу можно решить гораздо быстрее, если воспользоваться алгеброй логики при составлении предикатов. Ранее рассматривались разные операции и давались иллюстрации из теории множеств для каждой из них. Здесь, очевидно, наиболее подходит операция исключающего ИЛИ, т.е. XOR. В этом случае задача решается в один предикат (Рисунок 4.4). Программа на

Pascal такова:

program PRxor1; var x,y,R,a:real; L1,L2:boolean; begin

writeLn('введите коэффициент a и радиус R '); readLn(a,R);

writeLn('введите координаты x, y'); readLn(x,y);

L1:=y>a*sqr(x);

L2:=sqr(R)>sqrt(sqr(x)+sqr(y)); if L1 xor L2 then

writeLn('точка попадает') else

writeLn('точка не попадает'); end.

Начало

Ввод a, R

Ввод x, y

 

 

L1 := y>a*x2

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

L2 := R2>(x2+y2)

 

 

 

 

 

 

 

 

 

 

 

 

L1 XOR L2

 

 

 

 

 

 

 

 

 

 

 

 

 

Точка

 

 

 

 

Точка не

попадает

 

 

 

 

попадает

 

 

 

 

 

 

 

 

 

Конец

Рисунок 4.4 Проверка на попадание точки в заштрихованную область с использованием операции XOR

74 4.1 Задачи на развилки

Теперь рассмотрим такую задачу:

ПРИМЕР

Даны три неравных числа a,b,c . Выстроить их в порядке возрастания.

Если взять три числа и попытаться выстроить в порядке возрастания, то методом перебора можно прийти к заключению, что всего существует 6 вариантов порядка трех чисел. Вот эти варианты: « a,b,c », « a,c,b », « b, a,c », «

b,c, a », « c, a,b », « c,b, a ». Вообще, если вспомнить комбинаторику, то для N

объектов существует N ! перестановок. В нашем случае 3! = 6, что было показано выше.

Самый простой способ решения состоит в составлении сложных предикатов на проверку отношения сразу между всеми числами. В этом случае алгоритм состоит в последовательном переборе всех вариантов (Рисунок 4.5). Программа для этого случая такая:

Начало

Ввод a,b,c

(a<b) AND (b<c)

(a<c) AND (c<b)

a, b, c

(b<c) AND (c<a) a, c, b

(b<a) AND (a<c)

b, c, a

(c<a) AND (a<b)

b, a, c

c, b, a

c, a, b

Конец

Рисунок 4.5 Выстраивание трех чисел по возрастанию наглядным способом

4. Решение типовых задач на развилки и циклы

75

program UporABC1; var a,b,c:integer; begin

writeLn('введите три числа a, b, c'); readLn(a,b,c);

if (a<b) and (b<c) then writeLn('a=',a,' b=',b,' c=',c)

else if (a<c) and (c<b) then writeLn('a=',a,' c=',c,' b=',b)

else if (b<c) and (c<a) then writeLn('b=',b,' c=',c,' a=',a)

else if (b<a) and (a<c) then writeLn('b=',b,' a=',a,' c=',c)

else if (c<a) and (a<b) then writeLn('c=',c,' a=',a,' b=',b)

else

writeLn('c=',c,' b=',b,' a=',a); end.

Приведенный выше вариант обладает как достоинствами, так и недостатками. Среди достоинств следует отметить высокую наглядность решения, очень трудно что-то перепутать. Все условия для определенной последовательности проверяются сразу. Все последовательности идут друг за другом. Однако, есть и недостаток. Этот недостаток – время исполнения программы. Так, например, если мы будем иметь истинным только последнее сочетание ( c,b, a ), то для того, чтобы добраться до него, придется проверить на истинность все вышестоящие условия. Глубина вложенности самого последнего варианта равна пяти. Если мы захотим, чтобы вложенность самого дальнего варианта была меньше, то придется изменить алгоритм. Для этого придется проверять все условия раздельно. Алгоритм при этом усложнится, однако, среднее время его исполнения уменьшится. На такой простой задаче, какую мы сейчас рассматриваем это время засечь практически невозможно, однако важно понять сам принцип оптимизации алгоритмов. Ведь, во-первых, условий может быть намного больше, во-вторых, эти условия могут выполняться многократно, в третьих, в качестве условий могут выступать реальные физические процессы с большим характерным временем их протекания.

Более быстрый (но менее застрахованный от случайных ошибок) алгоритм может быть, например, таким как изображено на (Рисунок 4.6). Здесь самый глубокий вариант спрятан максимум за три предиката.

Программная реализация будет такая:

program UporABC2; var a,b,c:integer;

76

4.1 Задачи на развилки

begin

 

writeLn('введите три числа a, b, c');

 

readLn(a,b,c);

 

if a<b then

 

if b<c then

b=',b,'

c=',c)

 

writeLn('a=',a,'

 

else

 

 

 

 

 

 

 

 

 

 

 

if a>c then

 

a=',a,'

 

 

b=',b)

 

 

writeLn('c=',c,'

 

 

 

 

else

 

c=',c,'

 

 

b=',b)

 

 

writeLn('a=',a,'

 

 

 

 

else

 

 

 

 

 

 

 

 

 

 

 

if a<c then

a=',a,'

c=',c)

 

writeLn('b=',b,'

 

else

 

 

 

 

 

 

 

 

 

 

 

if b>c then

 

b=',b,'

 

 

a=',a)

 

 

writeLn('c=',c,'

 

 

 

 

else

 

c=',c,'

 

 

a=',a);

 

 

writeLn('b=',b,'

 

 

 

end.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Рисунок 4.6 Упорядочивание трех чисел (более быстрый вариант)

4. Решение типовых задач на развилки и циклы

77

4.2 Задачи на использование циклов

Задачи на использование циклов являются очень важными, поскольку практически в любой современной программе они присутствуют. Можно даже сказать, что именно использование циклов делает использование компьютера эффективным.

В предыдущей главе уже рассматривалась задача про табуляцию функции, для ее решения использовался один цикл. Можно условие той задачи немного модифицировать.

ПРИМЕР

Найти максимум среди значений функции y = −2x3 +5x2 +3x 1 при изменении x от 1 до 4 с шагом 0,1.

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

Составить такую программу, на самом деле, не очень сложно. Для этого нужно взять за максимум первую точку, а далее просматривать в цикле все оставшиеся точки и сравнивать их. Если последующая точка окажется больше предыдущей, то ее мы принимаем за максимум. Далее продолжаем эти

10

.

1

0

1

2

3

4

10

20

30

40

Рисунок 4.7 График кубического полинома

78

4.2 Задачи на использование циклов

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Рисунок 4.8 Поиск максимума среди значений

функции

действия до тех пор, пока все точки не будут рассмотрены. Описанный алгоритм представлен на (Рисунок 4.8).

4. Решение типовых задач на развилки и циклы

79

Программа такова: program maxF;

var x,y,max,Xmax:real; begin

cls; x:=-1;

max:=-2*x*x*x+5*x*x+3*x-1; Xmax:=x;

while x<=4 do begin

y:=-2*x*x*x+5*x*x+3*x-1; if y>max then

begin max:=y; Xmax:=x;

end;

x:=x+0.1;

end;

writeLn('максимум достигается в точке ', x:6:2); writeLn('и он равен ',max:10:5);

end.

В результате получается, что программа нам выведет такой результат:

максимум достигается в точке 4.00

и он равен

9.03200

что, судя по графику, соответствует истине.

А теперь усложним задачу таким образом, чтобы функция, которую придется табулировать, имела пару аргументов. Итак,

ПРИМЕР

Протабулировать функцию z = cos(y sin (x3 )), причем вывести только

те точки, которые больше чем 0,6 . Переменная y меняется на интервале [2;1] с шагом y =1, переменная x меняется на интервале [13;15] с шагом x = 0,8 .

Эта задача решается в два цикла, причем один будет вложен в другой. Пусть цикл по y будет внешним, а цикл по x – внутренним. Это означает,

что мысленно зафиксировав значение y мы изменяем весь диапазон значений

x . По своей сути изменение внутреннего цикла представляет простую табуляцию функции с одной переменной. Когда перебор всех значений переменных во внутреннем цикле окончен, мы меняем на значение шага переменную внешнего цикла и снова проходим по всем значениям цикла внутреннего. Действия повторяем до тех пор, пока не будет пройден весь диапазон изменения внешней переменной. Описанный алгоритм зафиксирован на (Рисунок 4.9).

80

4.2 Задачи на использование циклов

 

Рисунок 4.9 Табуляция функции с двумя переменными и вывод

 

только тех значений, которые удовлетворяют условию

Программная реализация такая:

Соседние файлы в папке Информатика