О.О.П / ооп / 4_кол / К курсовой / Методи побудови алгоритмів та їх аналіз. Караванова Т.П. / 1-23
.PDF„„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