Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции по TURBO PASCAL.doc
Скачиваний:
18
Добавлен:
04.11.2018
Размер:
1.13 Mб
Скачать
  1. Оптимизация программ

Допустим, что нам дано такое рекуррентное отношение:

a1 = 2;

ai = 2ai-1 + 3;

Нужно найти 20 член этой последовательности.

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

Сделайте это задание, прежде чем читать дальше!

Если вы добросовестно выполните это задание, то у вас получится такая программа:

program Example1;

var a : array [1..20] of integer;

i : integer;

begin

a[1] := 2;

for i := 1 to 20 do

a [i] := 2*a[i–1] + 3;

writeln (’Двадцатый элемент = ’, a[20]);

end.

Заметьте, что для вычисления 20 элемента программа находит последовательно каждый элемент, хотя для вычисления нового используется только последний элемент, остальные же лежат “мёртвым грузом”, так как далее они нигде не используются. Давайте попробуем избавиться от хранения излишней информаци. Другими словами, надо избавиться от массива. Так как при вычислении нового элемента нам надо знать, чему равен только предыдущий элемент, то будем его хранить в переменной pred, а новый элемент – в переменной novuj. Перед тем, как вычислять новый элемент, учтём, что бывший новый элемент становится предыдущим, поэтому содержание переменной pred надо будет поменять. Вот как изменится эта программа:

program Example2;

var pred, novyj, i : integer;

begin

novyj := 2;

for i := 1 to 20 do

begin

pred := novyj; { новый стал старым }

novyj := 2*pred + 3;

end;

writeln (’Двадцатый элемент = ’, novyj);

end.

Внимательно разберите этот пример! Если вам будет всё ясно, то вы, наверное, заметите, что в этой программе можно ещё избавиться от переменной pred, записав предложение цикла в таком виде:

for i := 1 to 20 do

novyj := 2*novyj + 3;

  1. Задача про интеллигентного студента.

Студент решил каждую неделю ходить в театр. Чтобы накопить для этого денег, он стал продавать газеты. Газеты он продает каждый день, с понедельника до пятницы и зарабатывает по 5 литов в день. В театр он ходит по субботам, покупая билет за 10 литов. Оставшиеся деньги он тратит в кафе. Но в один прекрасный день билеты начали дорожать… Цена их увеличивалась на 5% каждую неделю. Сколько недель студент сможет ещё ходить в театр на заработанные деньги (его заработок не изменяется)?

Для решения этой задачи удобно использовать рекуррентные соотношения. Запишем рекуррентную последовательность, в которой будут записаны цены билетов в театр на каждой неделе. Как известно, сначала билет стоил 10 литов:

a1 = 10

По условию задачи, через неделю цена увеличилась на 5 %. Значит:

a2 = a1*1.05 = 10*1.05 = 10.5 (литов).

И так продолжается каждую неделю. Значит, можно записать в общем виде цену билета на i-ой неделе:

ai = ai-1 * 1.05 , где i > 1.

Так как студент каждую неделю зарабатывает по 25 литов (5 дней по 5 литов), а оставшиеся после покупки билета деньги тратит в кафе, то задача сводится к нахождению номера недели, когда стоимость билета превысит 25 литов.

Программа, решающая эту задачу, будет такая:

program Teatr_i_Student;

var bilet : array [1..100] of real;

i : integer;

begin

bilet [1] := 10;

i := 1; {номер недели}

while bilet [i] <= 25 do

begin

i := i + 1;

bilet [i] := bilet [i-1] * 1.05;

end;

writeln (’Студенту не хватит денег на ’,

i, ’-ой неделе.’);

end.

Самостоятельное задание: перепишите эту программу так, чтоб не использовать массив!

Рассмотрим теперь усложнённый вариант этой задачи, когда студент лишние деньги не тратит, а откладывает на будущее. Тогда его капитал будет всё время изменяться. После первой недели он заработает 25 лит:

b1 = 25

В субботу он потратит некоторую сумму на билет (ровно столько, сколько он стоит, то есть a1) и через неделю зарабатывает опять 25 лит:

b2 = b1 – a1 + 25 = 25 – 10 + 25 = 40 (лит)

40 лит – это та сумма, которая будет у студента перед покупкой билета в театр на второй неделе.

Так продолжается каждую неделю:

bi = bi-1 – ai-1 + 25

Теперь студент сможет ходить в театр до тех пор, пока (условие после while) не ai <= 25, а пока ai <= bi .

Запишем это всё в алгоритм:

program Teatr_i_Student_2;

var bilet,

stud : array [1..100] of real;

i : integer;

begin

bilet [1] := 10;

stud [1] := 25;

i := 1;

while bilet [i] <= stud [i] do

begin

i := i + 1;

bilet [i] := bilet [i-1] * 1.05;

stud [i] := stud [i-1] - bilet [i-1] + 25;

end;

writeln (’Студенту не хватит денег на ’,

i, ’-ой неделе.’);

end.

Интересно заметить, что первая программа выдает ответ “на 20 неделе”, а вторая “на 34-ой неделе”.

Попробуйте самостоятельно переписать эту программу без использования массива! Если вы добросовестно выполните это задание, то у вас должно получится что-то вроде такого:

program Teatr_i_Student_3;

var bilet, stud : real;

i : integer;

begin

bilet := 10.0; stud := 25.0; i := 1;

while bilet <= stud do

begin

i := i + 1;

stud := stud - bilet + 25; {*}

bilet := bilet * 1.05; {**}

end;

writeln (’Студенту не хватит денег на ’,

i, ’-ой неделе.’);

end.

Обратите внимание на то, что в отличие от предыдущей программы, в этой переставлены местами помеченные строки. Объясните, почему возникла необходимость в этой перестановке?