Завдання ІІ етапу Всеукраїнської учнівської олімпіади з інформатики 2012-2013 н.р.
У М О В И Т А В К А З І В К И | |||||||||||||||||||||||||
Задача 1. POINTS Ім’я вхідного файлу: Ім’я вихідного файлу: Вихідний текст програми: Загальна кількість балів: |
Points.inp Points.out Points.* 100 балів |
На колі взято k точок (3 ≤ k ≤ 100), частина з яких (можливо всі) сполучені відрізками (хордами). Написати програму, що визначає min - мінімальну кількість хорд, які треба додатково провести, щоб утворився вписаний у коло опуклий многокутник, для якого дані хорди є сторонами або діагоналями, та n – число ще не проведених діагоналей утвореного многокутника. | |||||||||||||||||||||||
Формат вхідних даних: У єдиному рядку через пропуск записано числа x1 y1 x2 y2 … xi yi … – номери кінців даних хорд.
Формат вихідних даних: У єдиному рядку через пропуск записати числа min і n. Приклад вхідних та вихідних даних: Points.inp: 1 3 1 4 1 5 2 5 3 4 3 6 Points.out: 5 4 Вказівки до розв’язування. Перш за все необхідно визначити і записати у порядку зростання вершини многокутника, їх кількість – k дорівнює числу точок, що є кінцями даних хорд (на мал. 1.1 k = 6). Зауважимо, що точки, не сполучені відрізками, до уваги брати зовсім не слід, адже вони не використовуються у задачі. Саме тому k, яке в умові означає загальну кількість точок, на першому ж етапі розв’язування становитиме кількість задіяних точок.
У даному прикладі k дорівнює c – числу проведених хорд. Сторонами даного многокутника є хорди, які не мають внутрішніх перетинів, а його діагоналями (мал. 1.2) є хорди, що перетинаються. Дані задачі можна ізоморфно відобразити на відрізок з координатами 1 - 6 (мал. 1.3), поєднавши допоміжними відрізками координати, відповідні номерам кінців даних хорд. Кількість даних діагоналей многокутника d дорівнює кількості пар допоміжних відрізків, які мають не пусті і не рівні одному з відрізків перерізи. Проте, можна без цього обійтись, якщо помітити, що ті з хорд, що є сторонами многокутника, на кінцях мають точки, різниця номерів яких дорівнює 1. Якщо позначити p – число проведених сторін многокутника, то d = c – p.
![]() Число min – кількість не побудованих сторін многокутника (на мал. 1.2 зображені пунктиром) дорівнює k-(l – d), тобто min = k – p. Кількість не проведених діагоналей обчислюється за формулою n = k*(k - 3)/2 - d.
Основною робочою підпрограмою може бути логічна функція перевірки на перетин двох хорд. Кожну хорду зручно записати у записі lin = record begln, endln: integer; end, де begln та endln – координати початку та кінця хорд, а всі хорди – у масиві lines: array[1..100] of lin. Оцінка тестів до задачі Points:
Моє рішення на Free Pascal: | |||||||||||||||||||||||||
Задача 2. TRANSP Ім’я вхідного файлу: Ім’я вихідного файлу: Вихідний текст програми: Загальна кількість балів: |
Transp.inp Transp.out Transp.* 100 балів |
У місті працює мережа мікроавтобусів, що має кілька маршрутів, кожен із яких не замкнений і без самоперетинів. На кожному з маршрутів є по кілька зупинок, причому, деякі стоять на перетині маршрутів. Всі зупинки пронумеровані натураль-ными числами от 1 до n. Написати програму, яка за даним описом транспортної мережі визначить найменшу кількість пересадок, щоб дістатись від зупинки A до зупинки B. | |||||||||||||||||||||||
Формат вхідних даних: У першому рядку через пропуск записані числа: m (1 ≤ m ≤ 20) - кількість маршрутів, n (2 ≤ n ≤ 100) - кількість зупинок, A та B – номери зупинок, для яких потрібно підрахувати кількість пересадок. Кожен із наступних m рядків складається з pi чисел (2 ≤ pi ≤ 100) – номерів зупинок на i-му маршруті.
Формат вихідних даних: У єдиний рядок записати число k - найменшу кількість потрібних пересадок або число -1, якщо це не можливо.
Вказівки до розв’язування. Зобразимо транспортну мережу у вигляді графа, де зупинками будуть пронумеровані вершини. На малюнку 2.1, який відображає другий приклад, є два маршрути із зупинками 1 – 10. Для наочності зупинки першого маршруту з’єднаємо суцільними стрілками, а зупинки другого маршруту - пунктирними стрілками. Всі зупинки першого маршруту, що містить зупинку А, тобто №3, помітимо числом 0. Зупинки другого маршруту, який має спільні з першим маршрутом зупинки 4 та 7, помітимо числом 1 (малюнок 2.2). Очевидно, до будь-якої зупинки, поміченої числом 1, в тому числі і до зупинки В (№8) від зупинки А можна дістатись з однією пересадкою.
![]() Оцінка тестів до задачі TRANSP:
Мої вказівки до розв’язування. Збережемо інформацію про маршрути в масиві множин ss. Тобто для кожного маршруту, номери зупинок, які належать цьому маршруту будуть розміщені у відповідній множині. У множину s будемо поміщати маршрути, які досяжні з початкової зупинки не більше ніж за k пересадок.
Якщо мережа маршрутів буде не зв’язною, і з початкової зупинки до кінцевої, не зходячи з маршруту, добратися неможливо, то дана програма також зуміє це визначити: якщо на якомусь кроці ні одного нового маршруту до досяжним не добавиться, то кінцева зупинка не досяжна.
Моє рішення на Free Pascal: | |||||||||||||||||||||||||
Задача 3. RELATIV Ім’я вхідного файлу: Ім’я вихідного файлу: Вихідний текст програми: Загальна кількість балів: |
Relativ.inp Relativ.out Relativ.* 100 балів |
Якщо погодитись, що люди походять від Адама та Єви, то всі вони – родичі, правда, серед них небагато прямих родичів (батьки та діти, рідні брати та сестри і т.д.), більшість людей пов’язані між собою лише через спільних родичів. Написати програму, яка для n людей (1 ≤ n ≤ 100), що мають родинні зв’язки, визначає, якщо це можливо, число min (0 ≤ min ≤ n/2) - мінімальну кількість тих, що між собою не мають родинних зв’язків, і без кого решта з n людей втратять будь-які родинні зв’язки. | |||||||||||||||||||||||
Формат вхідних даних: На перетині i-го рядка та j-го стопчика квадратної таблиці n x n записано число 1, якщо i-а і j-а людини є прямими родичами, і число 0, якщо для цих людей відсутній прямий родинний зв’язок.
Формат вихідних даних: В єдиному рядку записати число min, або слово "not", якщо це число знайти не можливо.
Вказівки до розв’язування. Дані зручно проілюструвати на графі (див. мал. 3.1). У наведеному прикладі маємо справу іх зв’язним графом. Але, як видно з малюнка, відповідно умові, він двохдольний, тобто множина всіх вершин G=U∪V, де множини U=(1,2,3,4) та V=(5,6,7,8,9), причому U∩V=∅.
![]() 1) перевірки, чи він двохдольний; 2) якщо так, то визначення серед множин U і V тієї, яка має меншу кількість елементів. Найпростіше це можна зробити, здійснивши пошук в ширину, позначивши початкову вершину числом 0, безпосередньо пов’язані з нею вершини – числом 1, наступні вершини, безпосередньо пов’язані з вершинами, позначеними числом 1, позначити числом 2 і т.д. У наведеному графі одержимо (мал 3.2): ![]() Всі вершини множини U будуть позначені парними числами, а вершини множини V – непарними.
Оцінка тестів до задачі Relativ:
Моє рішення на Free Pascal: | |||||||||||||||||||||||||
Задача 4. PARTS Ім’я вхідного файлу: Ім’я вихідного файлу: Вихідний текст програми: Загальна кількість балів: |
Parts.inp Parts.out Parts.* 100 балів |
У прямокутному лісі, розбитому на квадрати, заблукав мисливець. Після того, як силами місцевого населення було безрезультатно обстежено k довільно розміщених квадратів, вирішено викликати рятівників для одночасного пошуку у всіх ще не обстежених ізольованих ділянках. Написати програму, яка визначить кількість необхідних бригад рятівників. | |||||||||||||||||||||||
Формат вхідних даних: У першому рядку записано через пропуск числа m та n – довжина і ширина лісу (m, n ≤ 50), у наступних i (i ≤ m*n) рядках по два числа xi та yi – координати обстежених квадратів.
Формат вихідних даних: У єдиному рядку записати кількість необхідних бригад рятівників.
Вказівки до розв’язування. З малюнку 4, де зображено ліс із розмірами та розміщенням обстежених квадратів (заштриховані) відповідно наведеному прикладу, видно, що ізольованих не обстежених ділянок три (вони пронумеровані). Для розв’язування задачі зручно використати структуру “черга”.
![]() Оцінка тестів до задачі PARTS:
Мої вказівки до розв’язування: Це класична задача на пошук в глибину графа. Зрозуміло, що треба обходити матрицю і якимось чином обчислювати кількість ізольованих не обстежених ділянок. Варіант вирішення такий: після того, як ми потрапляємо на ділянку, треба це зафіксувати збільшивши змінну-результат на одиницю. Щоб вдруге не порахувати одну і туй ж ділянку, відразу після відвідин необхідно її знищити, тобто присвоїти всім клітинам ділянки значення нуль.
Оскільки тест завдання не надто малий, варто написати процедуру знищення ділянок, назвемо її "count". Щоб під час виконання процедуру не «вискочити" за межі масиву, зробимо його не розміром m x n, а розмірів m+2 x n+2, це дасть нам можливість оточити шуканий масив розміром m x n нулями.
Моє рішення на Free Pascal: |