Сначала попробую восстановить условие задачи:
В какой-то там олимпиаде участвовало N человек. Каждый участник мог учиться в 7-11 классах и набрать от 0 до 70 баллов. 25% участников, набравших больше других баллов, становятся призерами. Известно, что если существуют участники, набравшее такое количество баллов, как и последний призер, то они тоже становятся призерами только в том случае, если они набрали больше половины баллов. Если нет — никто из них не становится призером. Необходимо узнать, какое минимальное количество баллов нужно было набрать, чтобы стать призером и найти количество призеров в каждой параллели. Входные данные: Первая строка: число участников N Последующие N строк: информация об участниках в виде <Фамилия> <Имя> <Параллель> <Количество баллов> Выходные данные: Первая строка: минимальное количество баллов Вторая строка: количество призеров в каждой параллели через пробел.
Задачу нужно решить на Pascal, притом максимально эффективно используя оперативную память и ресурсы процессора. Начнем.
var n,i,j,b,k,s,h,min:integer;
Объявляем целочисленные переменные:
n — количество участников
i — счетчик
j — второй счетчик
b — количество баллов
k — класс (параллель участника)
s — сумма участников, набравших данное количество баллов
h — количество призеров
min — минимальное количество баллов, необходимое для победы
results:array[0..70,7..11]:integer;
Двумерный массив для хранения результатов участников. Первое измерение — количество баллов, второе измерение — параллель. В ячейки записывается количество участников из данной параллели, набравшее данное количество баллов.
с: char;
Переменная символьного типа, необходима для посимвольного чтения входных данных
stop:boolean;
Позволит прекратить выполнение цикла определения минимального количества баллов.
С переменными все. Переходим к самой программе:
begin
readln(n);
Прочитали количество участников и записали его в N
for i:=1 to n do begin
repeat
read(c);
until c=' ';
repeat
read(c);
until c=' ';
readln(k,b);
results[b,k]:=results[b,k]+1;
end;
Пропустив фамилию и имя участника (они нам не нужны), считали информацию о параллелях и баллах каждого участника. Значения соответствующих ячеек массива увеличили на 1.
h:=n*0.25;
min:=70;
i:=70;
Определили количество призеров, установили счетчик в значение 70 и предположили, что минимальное количество баллов тоже 70.
while not stop do begin
s:=0;
for j:=7 to 11 do s:=s+results[i,j];
if (s>h) and (i>35) then begin
stop:=true;
min:=i;
end;
if (s>h) and (i>36) then stop:=true;
if s<h then begin
h:=h-s;
if s>0 then min:=i;
i:=i-1;
end;
end;
Находим минимальное количество баллов. Скаладываем количество участников, набравших определенное количество баллов (начиная с максимального), после чего вычитаем их из количества призеров. Как только призовых мест перестает хватать — проверяем, превышает ли количество баллов половину. В зависимости от результата, определяем min. В данном блоге движок заменяет знаки < и > на < и > (Lower then и Greater then), при написании реальной программы их надо будет заменить.
Мы определили минимальное количество баллов, можем вывести первую строку ответа:
writeln(min);
Теперь осталось посчитать количество призеров в каждой паралели.
for i:=7 to 11 do begin
s:=0;
for j:=min to 70 do begin
s:=s+results[j,i];
end;
write(s,' ');
end;
end.
С помощью вложенного цикла считаем количесто призеров в каждой параллели. Выводим информацию на экран.
Задача решена.
Приведу полный текст программы:
var n,i,j,b,k,s,h,min:integer;
results:array[0..70,7..11]:integer;
с: char;
stop:boolean;
begin
readln(n);
for i:=1 to n do begin
repeat
read(c);
until c=' ';
repeat
read(c);
until c=' ';
readln(k,b);
results[b,k]:=results[b,k]+1;
end;
h:=n*0.25;
min:=70;
i:=70;
while not stop do begin
s:=0;
for j:=7 to 11 do s:=s+results[i,j];
if (s>h) and (i>35) then begin
stop:=true;
min:=i;
end;
if (s>h) and (i>36) then stop:=true;
if s<h then begin
h:=h-s;
if s>0 then min:=i;
i:=i-1;
end;
end;
writeln(min);
for i:=7 to 11 do begin
s:=0;
for j:=min to 70 do begin
s:=s+results[j,i];
end;
write(s,' ');
end;
end.