Редакция для Парковка
Submitting an official solution before solving the problem yourself is a bannable offence.
Автор:
1. Идея
Для каждого запроса нужно:
- перевести время въезда и выезда в минуты от начала суток;
- найти длительность стоянки в минутах;
- округлить её вверх до целого числа часов;
- по количеству оплаченных часов посчитать цену по тарифу.
Задача сводится к аккуратной реализации нескольких простых шагов.
2. Наблюдения
1. Время удобно хранить в минутах
Строка вида HH:MM легко переводится в число минут:
- часы:
HH - минуты:
MM - всего минут от начала суток:
HH * 60 + MM
Например:
10:00->60010:01->601
Тогда длительность парковки равна просто разности:
d = finish - start
2. Нужно округление вверх до часов
Если машина стояла:
1минуту, оплачивается1час;60минут, тоже1час;61минуту, уже2часа.
Это классическое округление вверх:
h = (d + 59) // 60
Почему так работает:
- для
d = 1..60получаем1; - для
d = 61..120получаем2; - и так далее.
3. Тариф кусочный
Стоимость зависит от числа оплаченных часов h.
- если
h = 1, то цена100; - если
2 <= h <= 5, то:- первый час стоит
100, - остальные
h - 1часов по80;
- первый час стоит
- если
h >= 6, то:- первый час
100, - со 2-го по 5-й:
4часа по80, - остальные
h - 5часов по50.
- первый час
3. Алгоритм
Для каждого запроса:
- считать строки
t1иt2; - перевести
t1в минуты:hh1 = int(t1[0:2])mm1 = int(t1[3:5])m1 = hh1 * 60 + mm1
- аналогично перевести
t2вm2; - найти длительность:
d = m2 - m1; - найти число оплаченных часов:
h = (d + 59) // 60
- посчитать стоимость:
- если
h == 1, ответ100; - иначе если
h <= 5, ответ100 + (h - 1) * 80; - иначе ответ
100 + 4 * 80 + (h - 5) * 50;
- если
- вывести ответ.
4. Почему это работает
Докажем корректность по шагам.
Перевод времени в минуты
Момент времени HH:MM содержит HH полных часов и MM минут после них.
Значит, количество минут от начала суток равно HH * 60 + MM.
Следовательно, если въезд был в момент m1, а выезд — в момент m2, то длительность стоянки в минутах равна m2 - m1. По условию t1 < t2, поэтому длительность всегда положительна.
Округление вверх до часов
Оплачиваемое число часов должно быть равно:
1, если стоянка длилась от1до60минут;2, если от61до120минут;- ...
Формула h = (d + 59) // 60 именно это и делает:
- если
dделится на60, получаем точное число часов; - если не делится, добавление
59переносит результат к следующему целому часу.
Значит, h — это длина стоянки в часах с округлением вверх, как и требуется.
Подсчёт тарифа
Дальше остаётся точно следовать условию:
- первый оплаченный час всегда стоит
100; - часы со 2-го по 5-й стоят по
80; - начиная с 6-го — по
50.
Разбор по случаям:
h == 1
Есть только первый час, цена100.2 <= h <= 5
Первый час:100,
ещёh - 1часов по80,
итого100 + (h - 1) * 80.h >= 6
Первый час:100,
4 часа со 2-го по 5-й:4 * 80,
ещёh - 5часов по50,
итого100 + 4 * 80 + (h - 5) * 50.
Все варианты числа часов покрыты, значит алгоритм всегда выдаёт правильную стоимость.
5. Сложность
Для каждого запроса выполняется константное число операций.
- Время на один запрос:
O(1) - Общее время:
O(q) - Дополнительная память:
O(1)
Это легко укладывается в ограничения даже при q = 10^5.
6. Код на C++17
#include <iostream>
#include <string>
using namespace std;
int to_minutes(const string& s) {
int hh = (s[0] - '0') * 10 + (s[1] - '0');
int mm = (s[3] - '0') * 10 + (s[4] - '0');
return hh * 60 + mm;
}
int main() {
int q;
cin >> q;
for (int i = 0; i < q; i++) {
string t1, t2;
cin >> t1 >> t2;
int m1 = to_minutes(t1);
int m2 = to_minutes(t2);
int d = m2 - m1;
int h = (d + 59) / 60;
int cost;
if (h == 1) {
cost = 100;
} else if (h <= 5) {
cost = 100 + (h - 1) * 80;
} else {
cost = 100 + 4 * 80 + (h - 5) * 50;
}
cout << cost << "\n";
}
return 0;
}
7. Код на Python 3
q = int(input())
for _ in range(q):
t1, t2 = input().split()
h1 = int(t1[:2])
m1 = int(t1[3:])
h2 = int(t2[:2])
m2 = int(t2[3:])
start = h1 * 60 + m1
finish = h2 * 60 + m2
d = finish - start
h = (d + 59) // 60
if h == 1:
cost = 100
elif h <= 5:
cost = 100 + (h - 1) * 80
else:
cost = 100 + 4 * 80 + (h - 5) * 50
print(cost)
Комментарии