Задача 6890. Источник: Поляков. Задание КИМ 26
(Г. Шапошников) Начальник ведет прием граждан. При этом, при формировании очередности приема приняты следующие правила: 1) пенсионеры пользуются преимуществом перед всеми остальными гражданами; 2) женщины пользуются преимуществом перед мужчинами; 3) посетители одной категории принимаются в порядке «живой» очереди. Каждый приём длится определенное время (мин.).
Определите, сколько посетителей принято к заданному моменту времени и сколько из них относятся к той же категории, что и посетитель, находящийся на приеме в данный момент времени.
Входные данные представлены в файле 26-134.txt следующим образом. Первая строка входного файла содержит два натуральных числа N и T (1 ≤ N ≤ 1000, 1 ≤ T ≤ 10000) – количество принятых людей и интересующий нас момент времени, соответственно. Каждая из следующих N строк содержит три значения: время, когда посетитель пришел на прием; длительность приема; категория посетителя, одна из трех букв: W (женщина), M (мужчина) и G (пенсионер).
Запишите в ответе два числа: количество посетителей, принятых к моменту времени T (считая посетителя, находящегося на приёме в этот момент), и количество принятых посетителей той же категории, что и человек, находящийся на приеме в момент времени T.
Пример входного файла:
5 12
1 6 W
4 7 M
5 3 G
8 9 M
11 5 G
При таких исходных данных с 1-й по 7-ю минуту на приёме будет находиться женщина, пришедшая в 1-ю минуту. С 7-й по 10-ю минуту пенсионер, пришедший в 5-ю минуту. С 10-й по 17-ю – мужчина, пришедший в 4-ю минуту. Всего будет принято 3 человека, из них один мужчина, находящийся на приёме в момент 12. Ответ: 3 1.
Решение
В процессе решения задачи, самым простым будет удаление обработанных данных. Поэтому для решения на Python будем использовать списки, на PascalABC - динамические массивы, а на C++ - вектор. В качестве альтернативы возможно решение через статические массивы с удалением обработанных данных путем сдвига или использования в структуре флагового поля, является ли данная запись обработанной.
Отсортируем исходные данные по времени визита на прием. В переменной time будет содержаться время окончания приема очередного посетителя. Пока значение этой переменной меньше t? среди необработанных посетителей ищем того, кто имеет приоритет выше и пришел раньше. В соответствии с выбранным посетителем меняем значения счетчиков и переменной time. Обязательно необходимо учитывать, что посетитель мог, как стоять в очереди, так и прийти без очереди спустя какое-то время после освобождения начальника. Обработанного посетителя удаляем.
Python
f = open('26-134.txt')
n, t = map(int, f.readline().split())
a = []
for i in f:
x, y, z = i.split()
a.append([int(x), int(y), z])
a.sort(key=lambda x: x[0])
time = 0
g = 0
m = 0
w = 0
last = 0
while time < t:
z = 0
j = 1;
while j < len(a) and a[j][0] <= time:
if a[j][2] == 'G' and a[z][2] != 'G' or a[j][2] == 'W' and a[z][2] == 'M':
z = j
j += 1
if a[z][2] == 'G':
g += 1
last = g
elif a[z][2] == 'M':
m += 1
last = m
else:
w += 1
last = w
time = max(time + a[z][1], a[z][0] + a[z][1])
del a[z]
print(g + m + w, last)
PascalABC
type
Rec = record
start: Integer;
time: Integer;
category: String;
end;
var
n, t, i, j, z, min, time, g, m, w, last: Integer;
a: array of Rec = new Rec[1000];
tmp: Rec;
f: TEXT;
begin
Assign(f, '26-134.txt');
Reset(f);
Readln(f, n, t);
for i := 0 to n - 1 do
begin
Readln(f, a[i].start, a[i].time, a[i].category);
a[i].category := a[i].category[2:];
end;
for i := 0 to n - 2 do
begin
min := i;
for j := i + 1 to n - 1 do
if a[j].start < a[min].start then
min := j;
if min <> i then
begin
tmp := a[i];
a[i] := a[min];
a[min] := tmp;
end;
end;
time := 0;
g := 0;
m := 0;
w := 0;
last := 0;
while time < t do
begin
z := 0;
j := 1;
while (j < a.Length) and (a[j].start <= time) do
begin
if (a[j].category = 'G') and (a[z].category <> 'G') or
(a[j].category = 'W') and (a[z].category = 'M') then
z := j;
j := j + 1;
end;
if a[z].category = 'G' then
begin
g := g + 1;
last := g;
end
else if a[z].category = 'M' then
begin
m := m + 1;
last := m;
end
else
begin
w := w + 1;
last := w;
end;
if time + a[z].time > a[z].start + a[z].time then
time := time + a[z].time
else
time := a[z].start + a[z].time;
a := a[:z] + a[z + 1:];
end;
Writeln(g + m + w, ' ', last);
end.
C++
#include <iostream>
#include <vector>
#include <fstream>
using namespace std;
struct rec
{
int start;
int time;
string category;
};
int main()
{
ifstream f;
f.open("26-134.txt");
int n, t;
f >> n >> t;
vector<rec> a;
for (int i = 0; i < n; i++)
{
rec tmp;
f >> tmp.start >> tmp.time >> tmp.category;
a.push_back(tmp);
}
for (int i = 0; i < n - 1; i++)
{
int min = i;
for (int j = i + 1; j < n; j++)
if (a[j].start < a[min].start)
min = j;
if (min != i)
{
rec tmp = a[i];
a[i] = a[min];
a[min] = tmp;
}
}
int time = 0, g = 0, m = 0, w = 0, last = 0;
while (time < t)
{
int z = 0, j = 1;
while (j < a.size() && a[j].start <= time)
{
if (a[j].category == "G" && a[z].category != "G" ||
a[j].category == "W" && a[z].category == "M")
z = j;
j++;
}
if (a[z].category == "G")
{
g++;
last = g;
}
else if (a[z].category == "M")
{
m++;
last = m;
}
else
{
w++;
last = w;
}
if (time + a[z].time > a[z].start + a[z].time)
time = time + a[z].time;
else
time = a[z].start + a[z].time;
a.erase(a.begin() + z);
}
cout << g + m + w << " " << last << endl;
}
Ответ
80 77