Разберем решение олимпиадной задачи по программированию про парикмахерскую. В статье представлен алгоритм решения в текстовом виде и исходной код программы на языке C# с комментариями.
Условие задачи
В парикмахерской работает один мастер. Он тратит на одного клиента ровно 20 минут, а затем сразу переходит к следующему, если в очереди кто-то есть, либо ожидает, когда придет следующий клиент.
Даны времена прихода клиентов в парикмахерскую (в том порядке, в котором они при-ходили).
Также у каждого клиента есть характеристика, называемая степенью нетерпения. Она показывает, сколько человек может максимально находиться в очереди перед клиентом, чтобы он дождался своей очереди и не ушел раньше. Если в момент прихода клиента в очереди находится больше людей, чем степень его нетерпения, то он решает не ждать своей очереди и уходит. Клиент, который обслуживается в данный момент, также считается находящимся в очереди.
Требуется для каждого клиента указать время его выхода из парикмахерской.
Формат входного файла
В первой строке вводится натуральное число N, не превышающее 100 — количество клиентов.
В следующих N строках вводятся времена прихода клиентов — по два числа, обозначающие часы и минуты (часы — от 0 до 23, минуты — от 0 до 59) и степень его нетерпения (неотрицательное целое число не большее 100) — максимальное количество человек, которое он готов ждать впереди себя в очереди. Времена указаны в порядке возрастания (все времена различны).
Гарантируется, что всех клиентов успеют обслужить до полуночи.
Если для каких-то клиентов время окончания обслуживания одного клиента и время прихода другого совпадают, то можно считать, что в начале заканчивается обслуживание первого клиента, а потом приходит второй клиент.
Формат выходного файла
В выходной файл выведите N пар чисел: времена выхода из парикмахерской 1-го, 2-го, …, N-гo клиента (часы и минуты). Если на момент прихода клиента человек в очереди больше, чем степень его нетерпения, то можно считать, что время его ухода равно времени прихода.
Примеры
Алгоритм решения
Примем, что нумерация элементов в массиве начинается с нуля.
- Прочитать из входного файла первую строку (это число N).
- Создать массив длиной N для хранения времени входа клиентов в парикмахерскую (массив элементов типа Time, DateTime или что-то в этом роде). Назовем его input.
- Создать массив целых чисел длиной N для хранения степени нетерпения каждого клиента. Назовем его impatience.
- Прочитать из входного файла N строк и заполнить прочитанными данными массивы input и impatience.
- Создать массив длиной N для хранения времени выхода клиентов из парикмахерской (массив элементов типа Time, DateTime или что-то в этом роде). Назовем его output.
- В ЦИКЛЕ for от 0 до N – 1 (по i):
1. Объявим переменную целого типа k = 0. Это количество людей в очереди перед i-м клиентом.
2. Объявим переменную целого типа kN = 0. Это расстояние в рамках массива от i-го клиента до первого в очереди перед ним.
3. Найдем эти значения путем перебора элементов массива output от i – 1 до 0 (переменная цикла j) и сравнивая значения времени с input[i]. (ЕСЛИ output[j] > input[i], ТО k = k + 1 и kN = i — j).
4. ЕСЛИ степень нетерпения i-го клиента меньше k, ТО output[i] = input[i] (значит он не будет ждать и уходит); ИНАЧЕ output[i] = input[i] + 20 минут (в начале примем, что ему возможно не нужно будет ждать очереди), далее в цикле от i – 1 до i – kN по j: ЕСЛИ output[j] > input[i] (значит i-й клиент сразу после j-го), ТО output[i] = output[j] + 20 минут и выходим из цикла по j. - Вывести значения массива output в выходной файл.
Решение задачи на языке C#
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Saloon { class Program { static void Main(string[] args) { // объект для чтения данных из файла StreamReader sr = new StreamReader("saloon.in"); // читаем N int N = Convert.ToInt32(sr.ReadLine()); // создаем массивы: для времени входа клиентов в парикмахерскую и для их степени нетерпения DateTime[] input = new DateTime[N]; int[] impatience = new int[N]; // читаем данные из файла for (int i = 0; i < N; i++) { string[] client = sr.ReadLine().Split(' '); input[i] = new DateTime(1, 1, 1, Convert.ToInt32(client[0]), Convert.ToInt32(client[1]), 0); impatience[i] = Convert.ToInt32(client[2]); } // закрываем входной поток sr.Close(); // массив структур для времени выхода клиентов из парикмахерской DateTime[] output = new DateTime[N]; for (int i = 0; i < N; i++) { int k = 0; // количество людей в очереди перед i-м клиентом int kN = 0; // расстояние в рамках массива от i-го клиента до первого в очереди перед ним // найдем эти значения for (int j = i - 1; j >= 0; j--) if (output[j] > input[i]) { k++; kN = i - j; } if (impatience[i] < k) output[i] = input[i]; else { output[i] = input[i].AddMinutes(20); for (int j = i - 1; j >= i - kN; j--) if (output[j] > input[i]) { output[i] = output[j].AddMinutes(20); break; } } } // объект для вывода данных в файл StreamWriter sw = new StreamWriter("saloon.out"); // вывод результатов в файл for (int i = 0; i < N; i++) sw.WriteLine(output[i].Hour + " " + output[i].Minute); // закрываем выходной поток sw.Close(); } } } |
Поделиться в соц. сетях: