Скачиваний:
35
Добавлен:
30.05.2020
Размер:
351.31 Кб
Скачать

„„UT.O

/у Іі і " %

ммшІ, WA 0 Т.П. Караванова

ББК 32.81я721 К21

Схвалено комісією з інформатики Навчально-методичної ради з питань освіти Міністерства освіти і науки України (лист №1.4/18-1450 від 22.06.2007р.)

Р е ц е н з е н т и :

Тимофієва Є.М. - канд. фіз.-мат. наук, доцент Чернівецького національного університету імені Юрія Федьковича;

Мельник В.І. — учитель інформатики Ліцею інформаційних технологій м. Олександрії, заслужений учитель України

Караванова, Т.П.

К21 Інформатика : методи побудови алгоритмів та їх ана­ ліз : обчисл. алгоритми : навч. посіб. для 9-10 кл . з поглибл. вивч. інформатики / Т.П. Караванова. - К. : Генеза, 2009. - 336 с. : іл. - Бібліогр.: с. 331.

ISBN 978-966-504-731-5.

Навчальний посібник містить достатньо повний об'єм мате­ ріалу, необхідний для оволодіння навичками побудови алго­ ритмів різного рівня складності, оптимізації методів їх розробки, оцінки ефективності виконання алгоритмів, вироблення нави­ чок тестування програм, що реалізують розроблені алгоритми. У посібнику розглянуто питання оптимізації алгоритмів з вико­ ристанням елементів комбінаторики, теорії графів, лінійного та динамічного програмування, обчислювальної геометрії, алгебра­ їчних методів розв'язування алгоритмічних задач.

Цей навчальний посібник може бути корисний як при ви­ вченні алгоритмізації у шкільному курсі з поглибленим вивчен­ ням інформатики, так і при підготовці учнів інших навчальних закладів до олімпіад, турнірів, конкурсів з інформатики.

Посібник призначений для широкого кола читачів, учителів, а також для учнів, що вивчають інформатику за поглибленою програмою, учнів старших класів загальноосвітніх навчальних закладів, які готуються до олімпіад, конкурсів, турнірів з інфор­ матики, для студентів училищ, технікумів, середніх спеціаль­ них навчальних закладів та ВНЗ.

Рекомендується також як навчальний посібник для само­ стійного вивчення.

 

ББК 32.81я721

 

©Караванова Т.П., 2007

ISBN 978-966-504-731-5

©Видавництво «Генеза»,'

оригінал-макет, 2009

ВІД АВТОРА

Даний навчальний посібник є логічним продовженням посібника «Методи побудови алгоритмів та їх аналіз. Необчислювальні алгоритми». Після ознайомлення з різноманітними алгоритмами, які можна назвати базовими для побудови складних алгоритмів, слід переходити до побудови оптимізаційних алгоритмів.

Володіючи базовими алгоритмічними структурами - ліній­ ними, розгалуженими і циклічними, можна побудувати алго­ ритм розв'язку практично будь-якої задачі. Розв'язання склад­ них алгоритмічних задач, метою яких є пошук кращого з усіх можливих варіантів розв'язків, може бути реалізовано за допо­ могою повнопереборних алгоритмів. Однак існують різні мето­ ди, які дають змогу оптимізувати такі задачі і розв'язати їх за мінімальний час. Методи розв'язування таких задач представ­ лені в інформатиці різними розділами: теорія графів, лінійне та динамічне програмування тощо.

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

Аналіз значної кількості робіт відомих авторів, присвяче­ них питанням вивчення методів розв'язування складних алго­ ритмічних задач, дав мені змогу підійти до розгляду методів побудови алгоритмів з різних точок зору і розташувати ма­ теріал у найбільш логічній і зручній послідовності.

Оскільки даний навчальний посібник у першу чергу орієнто­ вано на учнів загальноосвітніх навчальних закладів і молод­ ших курсів вищих навчальних закладів, то його матеріал мак­ симально адаптований саме для цієї вікової категорії читачів.

До посібника увійшли не тільки теми, передбачені програ­ мою поглибленого вивчення інформатики, а й матеріал, не­ обхідний для підготовки до олімпіад, турнірів, конкурсів тощо.

Достатній досвід роботи з учнями Чернівецького міського ліцею № 1, робота з обдарованими дітьми під час підготовки до різного рівня олімпіад з інформатики дають підстави сподіва­ тися, що даний навчальний посібник буде корисним учителям, тренерам та їхнім учням.

Тетяна Караванова

З

РозділІ

9 0 1 ) 0 1 1 : 0 10

 

10 0 1

0 111

10 1 1 1 0 0

0 1

о о о o l i o і

 

10

10 0

10 1

В 01

10 10 0 1

0

0 1 1 1 0 11

10 11

о

о і

о с а

 

і

. 1

0

 

 

і

АЛГОРИТМИ ДЛЯ РОБОТИ З ДОВГИМИ ЧИСЛАМИ

Дані алгоритми мають коротку і влучну назву - довга ариф­ метика. Про що йдеться? Ми вже розглядали питання обмеже­ ності значень різних типів даних і наводили приклад обчислен­ ня значень га! для га > 7 у разі, коли результат описано як цілу змінну. При цьому матимемо неправильну відповідь. І все це тому, що значення 8! = 40 320, а тип integer має верхню межу значень 32 767. Під час обчислення відповіді для га = 8 за допо­ могою простенької програми

program factorial; varf, і, n: integer;

begin read(n); f: = 1;

for і := 1 to n do f =f * j-

і . і i,

writeln(f)

end;

отримаємо результат -25 216, який демонструє описану ситуацію. Отже, ми вийшли за межу значень даного типу і не можемо отри­ мати правильний результат. Така ситуація може трапитися не ли­ ше під час обчислення факторіала, а, наприклад, при спробах отри­ мати значення аь при цілих, але великих значеннях аргументів.

Вихід із цієї ситуації є, якщо подати число у вигляді масиву окремих його цифр. Алгоритми довгої арифметики передба­ чають поцифрову обробку заданих чисел, а тому є циклічними. Оскільки йдеться про арифметику, то й алгоритми, які реалізу­ ються над довгими числами, - це алгоритми додавання, віднімання, множення та ділення. І ще одна умова - розгляда­ тимемо лише цілочислову арифметику.

Отже, нам потрібно буде реалізувати алгоритми виконання арифметичних дій над числами, що подані у вигляді масивів цифр. Розглядаючи системи числення, ми раніше реалізовува­ ли ці алгоритми для систем числення з основами Р. Нагадаємо їх та дещо модифікуємо.

Розглянемо ті арифметичні дії, які найчастіше трапляються в задачах, а саме: додавання, віднімання і множення.

Додавання довгих цілих чисел

Нехай задано масиви At, Вр і = 1, 2, ..., п, елементами яких є цифри 10-ї системи числення. Розробимо алгоритм додавання цих двох довгих чисел. Для цього необхідно порозрядно дода­ вати цифри двох чисел і контролювати отриманий результат: якщо він менший за 10, то це і є наступна цифра числа-ре- зультату; якщо ні, то необхідно відокремити цифри одиниць і десятків отриманого результату і продовжити додавання на­ ступних розрядів.

Запишемо у словесній формі алгоритм додавання у стовпчик двох десяткових чисел.

1.Нехай п - кількість цифр у першому числі, а т - у друго­ му. Тоді визначимо k = max(n, т).

2.Визначити і := 1, с := 0 (с - кількість десятків у додаванні попереднього розряду).

3.Нехай аі - і-та цифра першого доданка, bt - другого, а rezi - результату. Визначити с := at + bt + с.

4.Якщо с < 10, тоді визначити rezi := с і перейти до п. 6.

5.Якщо с > 10, тоді визначити значення і-го розряду числа-

результату як rezt := <кількість одиниць числа с> , а значення, яке необхідно буде додати у наступному розряді, - як с := к і л ь ­ кість десятків числа с > .

6.Якщо і < k, то і := і + 1 та перейти до п. 3.

7.Якщо с > 0, то k := k + 1, rezk := с, що означатиме збіль­ шення розрядності числа-результату.

8.Вивести елементи масиву гаг.

Реалізуємо фрагмент цього алгоритму (п. 1-6) у вигляді про­ цедури:

procedure add(var a: mas; b: mas; var k: word); var i: word;

begin

if n > m t h e n k := n e l s e k := m; {Визначення максимальної довжини двох чисел.}

с:=0;

for і := 1 to k do

b e g i n

 

{Визначення суми цифр поточного розряду}

С := а[і] + Ь[і] + с;

 

{і десятків попереднього.}

а [І] := С m o d 10;

{Кількість одиниць є поточною цифрою результату,}

С := c d i v 10 {а кількість десятків запам'ятаємо для наступного додавання.}

e n d ;

 

 

{Якщо після останнього}

if с <> 0 then begin inc(k); a[k] := c end;

{додавання кількість}

e n d ;

{десятків не нульова, то збільшуємо розрядність числа-результату.}

5

Зверніть увагу на те, що для отримання результату додаван­ ня використовується масив а. Це робиться з метою економи пам'яті комп'ютера і тому, що після обробки поточна цифра масиву а вже надалі не потрібна.

Для використання цієї процедури в основній програмі треба зробити такий опис власних типів:

type mas = array[1..1000] of byte;

І ще одна пропозиція: для того щоб користувачу не доводи­ лося вводити цифри масивів окремо по одній, можна організу­ вати імітацію цього введення, як звичайного числа:

procedure input(var х: mas; var k: word); var i: word;

err: integer; begin

for і := k downto 1 do begin

ch := ReadKey; write(ch); val(ch, x[i], err);

end;

writeln;

end;

Звернемо увагу на те, що у запропонованому алгоритмі та відповідній процедурі розглядалося додавання чисел по одній цифрі з описом змінних, що зберігають їх значення, типом byte. Однак це неекономне використання даного типу, оскіль­ ки максимальне значення цього типу 255. Природно виникає запитання: чи не можна під час додавання обробляти одночас­ но двоцифрові числа?

Розглянемо приклад: 1234 + 5642 = 6876.

Розіб'ємо обидва числа таким чином: 1234 = 1200 + 34, 5642 = = 5600 + 42. Зрозуміло, що відповідь від цього не зміниться, але додавання тепер може відбуватися так: (1200 4- 5600) + (34 + + 42). Отже, можна вдосконалити алгоритм, розбиваючи за­ дані числа, тобто елементи масивів, на групи по дві цифри, і ви­ конувати їх додавання. При цьому отриманий результат розділяємо на такі дві частини: перша - останні дві цифри, дру­ га - кількість сотень. Перша - це і буде результат додавання поточних двох розрядів, а друга - інформація, що запам'ято­ вується для додавання наступних двох розрядів. А чи не вийде­ мо під час додавання двоцифрових чисел за межі типу byte? Найбільші числа, які ми можемо додавати, це 99, а їхня сума дорівнює 198. Отже, усе залишиться в межах обраного типу.

Логічними є наступні міркування: а чому не тип word? Справ­ ді, користуючись таким типом, можна розбивати задані числа на групи по 4 цифри, починаючи з найменшої цифри. При цьо-

6

му додавання максимально можливих чотирицифрових чисел (9999 + 9999 = 19 998) не вийде за межі даного типу (65 535). Якщо взяти тип longint, то можна розбивати числа на групи по 9 цифр, оскільки максимальним значенням цього типу є десятицифрове число 2 147 483 647. Перевірка додавання двох максимальних за значенням дев'ятицифрових чисел 999 999 999 + 999 999 999 = 1 999 999 998 указує, що ми не виходимо за межі обраного типу.

Що дає розбиття заданих чисел на групи, більші за кількіс­ тю цифр? Аргументи не потребують доведення:

-значно зменшується кількість циклів під час додавання чисел;

-використовуються готові алгоритми для додавання двох цілих чисел.

Модифікована процедура введення вхідних даних з вико­ ристанням типу word виглядатиме так:

procedure input(var х: mas; var k: word); var і, j, L: word;

err: integer; begin

k := k div 4; L := k m o d 4;

{Визначення кількості k повних і L неповних груп.}

if L О 0

 

 

 

{Якщо є неповна група, то вводяться її цифри.}

t h e n

 

 

 

 

b e g i n

 

 

 

 

inc(k);

st

:=

";

 

f o r i :=

1

to

L do

 

b e g i n

 

 

 

 

ch := R e a d K e y ; w r i t e ( c h ) ;

st := st + ch;

 

e n d ;

 

 

 

 

val(st, x [ k ] , err);

 

d e c ( k )

 

 

 

 

e n d ;

 

 

 

 

f o r І := 1 to k do

 

{Вводяться повні групи цифр.}

b e g i n

 

 

 

 

s t : = " ;

 

 

 

 

f o r j :- 1 to 4 do

{Посимвольно вводяться цифри поточної групи.}

b e g i n

 

 

 

 

ch := R e a d K e y ; w r i t e ( c h ) ;

st := St + Ch;

{Накопичення цифр поточної групи.}

end;

 

 

 

 

val(st, x[i], err);

{Переведення у числовий вигляд.}

end;

 

 

 

 

if L <> 0 t h e n inc(k);

{Якщо існує старша неповна група, то кількість груп}

 

 

 

 

{збільшується на 1.}

w r i t e l n ; e n d ;

7

Модифікований варіант процедури додавання з використан­ ням типу word може бути таким:

procedure add(var a, b: mas; var k: word); var i: word;

begin

if n > m then k := n else k := m; c:=0;

for і := 1 to k do begin

c:=a[i] + b[i] + c;

a[i] := C m o d 10000;

{Виділення результуючої групи цифр.}

С := С div 10000

{Виділення цифри, що виходить за розрядність групи.}

e n d ;

 

 

if с <> 0 t h e n b e g i n inc(k); a[k]

:= c e n d ;

e n d ;

Звернемо увагу також і на той момент, що, як і для варіанту обробки довгих чисел окремими цифрами, для отримання ре­ зультату додавання двох довгих чисел розбиттям на групи не використовується ще один результуючий масив. Для економії пам'яті комп'ютера можна використовувати вже оброблені еле­ менти масиву а.

Виведення результату можна виконати за допомогою такого фрагмента програми:

w r i t e ( a [ k ] ) ;

{Виведення першої групи цифр.}

f o r і := k - 1 d o w n t o 1 do

 

b e g i n

 

Str(a[i], St);

{Представлення м групи цифр у вигляді рядка.}

f o r j := 1 to 4 - length(st) do

{Виведення на початку ;'-ї групи цифр}

write('O');

{необхідної кількості нулів.}

w r i t e ( a [ i ] ) ;

{Виведення /-Ї групи цифр.}

e n d ;

 

Процес тестування складених алгоритмів необхідно поча­ ти з додавання «зручних» чисел, сума цифр відповідних роз­ рядів яких не перевищує 9, а самі цифри коливаються в межах від 1 до 8. Наступним кроком тестування може бути перевірка додавання чисел, серед цифр яких є 0, однак сума цифр відповідних розрядів не перевищує 9. Складнішою перевіркою має бути додавання чисел, сума цифр яких перевищує 9, але цифрами наступних старших розрядів обох чисел є 0.1 останньою перевіркою може стати тест для двох чисел, сума цифр яких пе­ ревищує 9.

Усі ці тести необхідно застосувати до алгоритмів додавання з однаковою розрядністю доданків, різною розрядністю до­ данків та з різним описом вхідних даних.

8

Завдання

1.Розробити діалогову меню-орієнтовану програму додавання цілих додатних чисел, використовуючи тип byte, і протесту­ вати її за такими критеріями:

-обидва числа однакової розрядності, що кратна числу 2, та сума яких має таку саму розрядність;

-обидва числа однакової розряд ності, що кратна числу 2, та сума яких має більшу розряд ність;

-розрядність першого числа більша від розрядності друго­ го, але при цьому розрядність обох чисел кратна числу 2;

-розрядність першого числа більша від розрядності другого, але при цьому розрядність одного з них не кратна числу 2;

-розрядність першого числа менша від розрядності друго­ го, але при цьому розрядність обох чисел кратна числу 2;

-розрядність першого числа менша від розрядності другого, але при цьому розрядність одного з них не кратна числу 2.

2.Розробити діалогову меню-орієнтовану програму додавання цілих додатних чисел, використовуючи тип word:

-обидва числа однакової розрядності, що кратна числу 4, та сума яких має таку саму розрядність;

-обидва числа однакової розрядності, що кратна числу 4, та сума яких має більшу розрядність;

-розрядність першого числа більша від розрядності друго­ го, але при цьому розрядність обох чисел кратна числу 4;

-розрядність першого числа більша від розрядності другого, але при цьому розрядність одного з них не кратна числу 4;

-розрядність першого числа менша від розрядності друго­ го, але при цьому розрядність обох чисел кратна числу 4;

-розрядність першого числа менша від розрядності другого, але при цьому розрядність одного з них не кратна числу 4.

3.Розробити діалогову меню-орієнтовану програму додавання цілих додатних чисел, використовуючи тип longint:

-обидва числа однакової розрядності, що кратна числу 9, та сума яких має таку саму розрядність;

-обидва числа однакової розрядності, що кратна числу 9, та сума яких має більшу розрядність;

-розрядність першого числа більша від розрядності друго­ го, але при цьому розрядність обох чисел кратна числу 9;

-розрядність першого числа більша від розрядності другого, але при цьому розрядність одного з них не кратна числу 9;

-розрядність першого числа менша від розрядності друго­ го, але при цьому розрядність обох чисел кратна числу 9;

-розрядність першого числа менша від розрядності другого, але при цьому розрядність одного з них не кратна числу 9.

4.Виконати завдання 1-3 для вхідних даних довжиною 32 000 цифр, згенерованих випадковим чином, що вводяться із файлу.

5.Зробити письмовий аналіз виконання завдань 1-4.

9

z

 

Запитання для самоконтролю

1. Які алгоритми називають алгоритмами роботи з довгими чис­

 

 

лами?

 

2.

У чому полягає необхідність створення цих алгоритмів? Обґрун­

 

 

туйте свою відповідь.

 

3.

Яким чином представляються числа в алгоритмах довгої ариф­

 

 

метики?

 

4.

Опишіть алгоритм додавання цілих чисел.

 

5.

Представте алгоритм додавання цілих довгих чисел у вигляді

 

 

процедури мовою Pascal.

 

6.

Яким чином краще організувати введення початкових даних для

 

 

алгоритму додавання цілих довгих чисел?

 

7.

Яким чином можна модифікувати процедуру додавання цілих

 

 

довгих чисел?

 

8.

У чому полягають переваги розбиття цифр довгих чисел на гру­

 

 

пи, в яких більше однієї цифри у кожній?

 

9.

Яку роль у раціональному розбитті цифр довгих чисел на групи

 

 

відіграють стандартні типи змінних, що описують цілі числа у

 

 

Pascal?

10. Запишіть модифікований варіант процедури введення почат­ кових даних у разі використання типу word для зберігання груп цифр доданків.

11. Запишіть модифікований варіант процедури додавання двох довгих цілих чисел у разі використання типу word для зберіган­ ня груп цифр цих чисел.

Віднімання довгих цілих чисел

Алгоритм віднімання довгих чисел так само, як і додавання, базується на алгоритмі виконання цієї дії над двома числами у стовпчик.

Домовимося розглядати випадок, коли зменшуване не пере­ вищуватиме від'ємник. Інакше необхідно спочатку задані числа поміняти місцями, а обчислений результат виводити зі знаком «-». Саме тому в наведеному далі алгоритмі перевірка необхідності обміну початкових даних відсутня.

Розглянемо спочатку випадок, коли дії віднімання викону­ ються над окремими цифрами заданих чисел. Нагадаємо сам алгоритм, який нам відомий з початкової школи.

1.Нехай п - кількість цифр у зменшуваному, а т - у від'ємнику. Для обчислення результату віднімання визначимо кількість переглядів елементів масивів я.

2.Визначити і := 1, с := 0 (с - ознака позичення 1 у наступ­ ному розряді).

3.Нехай at - t-та цифра зменшуваного, bt - від'ємника, a rezl - результату.

4.Якщо аі > 0 і с = 1, тобто з цього розряду у попередньому відніманні позичена 1, то зменшити аі на 1, ознаку позики 1

10

Соседние файлы в папке Методи побудови алгоритмів та їх аналіз. Караванова Т.П.