Разбор задач олимпиады 9

advertisement
Министерство образования и науки Республики Хакасия
Муниципальный этап ВсОШ по информатике 2014-2015 учебный год
Разбор задач олимпиады 9-11 классы
При проверке задач с помощью тестирующей программы(100 тестов), баллами оценки
задачи будут количество пройденных тестов. При проверке текста задачи, необходимо
провести проверку в следующей последовательности: компиляция исходного текста
программы;
последовательное
исполнение
программы
с
входными
данными,
соответствующими тестам из набора тестов для данной задачи. При компиляции исходного
текста программы, необходимо учитывать следующее. жюри должно использовать вполне
определенные команды компиляции, соответствующие выбранному участником языку
программирования; необходимо учитывать, что размер файла с исходным текстом программы
не должен больше 256 КБ, а время компиляции программы не должно превышать одной
минуты. Итоговая оценка проверки решений всех задач олимпиады для каждого участника
формируется как сумма полученных этим участником баллов за каждую задачу.
Общие критерии оценивания для всех задач
1. Правильное полное решение каждой задачи — 100 баллов.
2. Решение задачи с недочетами (модельные, арифметические или логические ошибки,
неполное объяснение отдельных положений или невыполнение части условий задачи) – 80 –
50 баллов
3. Неполное решение, решение с грубыми ошибками – 40 – 20 баллов.
4. Отсутствие решения, но есть отдельные верные блоки решений – 10 баллов.
5. Задача не решалась или отсутствуют даже отдельные верные блоки решений – 0
баллов.
Задача 1. Черно-белые изображения (Время: 2 сек. Память: 16 Мб Баллы: 100)
Имя входного файла:
INPUT.TXT
Имя выходного файла:
OUTPUT.TXT
Максимальное время работы на одном тесте:
2 секунды
Максимальный объем используемой памяти:
64 мегабайта
Одна из базовых задач компьютерной графики – обработка черно-белых изображений.
Изображения можно представить в виде прямоугольников шириной w и высотой h, разбитых
на w×h единичных квадратов, каждый из которых имеет либо белый, либо черный цвет. Такие
единичные квадраты называются пикселями. В памяти компьютера сами изображения
хранятся в виде прямоугольных таблиц, содержащих нули и единицы.
Во многих областях очень часто возникает задача комбинации изображений. Одним из
простейших методов комбинации, который используется при работе с черно-белыми
изображениями, является попиксельное применение некоторой логической операции. Это
означает, что значение пикселя результата получается применением этой логической
операции к соответствующим пикселям аргументов. Логическая операция от двух аргументов
обычно задается таблицей истинности, которая содержит значения операции для всех
возможных комбинаций аргументов. Например, для операции «исключающее ИЛИ» эта
таблица выглядит так.
Первый аргумент
Второй аргумент
Результат
0
0
0
0
1
1
1
0
1
1
1
0
Требуется написать программу, которая вычислит результат попиксельного применения
заданной логической операции к двум черно-белым изображениям одинакового размера.
Формат входных данных
Министерство образования и науки Республики Хакасия
Муниципальный этап ВсОШ по информатике 2014-2015 учебный год
Первая строка входного файла содержит два целых числа w и h (1 ≤ w, h ≤ 100).
Последующие h строк описывают первое изображение и каждая из этих строк содержит w
символов, каждый из которых равен нулю или единице. Далее следует описание второго
изображения в аналогичном формате. Последняя строка входного файла содержит описание
логической операции в виде четырех чисел, каждое из которых – ноль или единица. Первое из
них есть результат применения логической операции в случае, если оба аргумента – нули,
второе – результат в случае, если первый аргумент – ноль, второй – единица, третье –
результат в случае, если первый аргумент – единица, второй – ноль, а четвертый – в случае,
если оба аргумента – единицы.
Формат выходных данных
В выходной файл необходимо вывести результат применения заданной логической
операции к изображениям в том же формате, в котором изображения заданы во входном
файле.
Пример входных и выходных данных
INPUT.TXT
OUTPUT.TXT
53
11110
01000
11100
11110
11110
01000
10110
00010
10110
0110
Разбор задачи:
Решение данной задачи в основном заключается в непосредственной аккуратной
реализации операции, описанной в условии задачи. Для хранения заданной логической
операции можно использовать массив целочисленного типа d[0..1,0..1], элемент которого
d[i,j] хранит результат логической операции с первым аргументом i и вторым аргументом j.
Таким образом, значение пикселя результата с координатами (x, y) будет равно
d[a[x,y],b[x,y]], где a[1..h,1..w] и b[1..h,1..w] – целочисленные матрицы, хранящие исходные
изображения. При реализации решения особое внимание следует уделить этапу считывания
исходных изображений и описания логической операции из входного файла, а также выводу
результата работы программы в выходной файл.
В чем подвох?
Многие не могут считать данные из файла INPUT.TXT. Обратите внимание, что во
входном файле, пробелы между символами есть только в первой строке. Во всех
остальных строках, между символами нет пробелов!
Текст программы на Паскале:
Var
P, Q :array [1..100,1..100] ofboolean;
O :array [False..True, False..True] of char;
x, y, w, h : byte;
c : char;
f : text;
begin
Assign(f,'bw.in');
Reset(f);
Readln(f,w,h);
for y:=1 to h do
begin
Министерство образования и науки Республики Хакасия
Муниципальный этап ВсОШ по информатике 2014-2015 учебный год
for x:=1 to w do
begin
read(f,c);
if c='1' then
P[x,y]:=True
else
P[x,y]:=False;
end;
Readln (f);
end;
for y:=1 to h do
begin
for x:=1 to w do
begin
read(f,c);
if c='1' then
Q[x,y]:=True
else Q[x,y]:=False;
end;
Readln (f);
end;
Read(f, O[False,False], O[False,True], O[True,False], O[True,True]);
Close(f);
Assign(f,'bw.out');
Rewrite(f);
for y:=1 to h do
begin
for x:=1 to w do
Write(f, O[P[x,y],Q[x,y]]);
Writeln(f);
end;
Close(f);
end.
Задача 2.Сад короля (Время: 2 сек. Память: 16 Мб Баллы: 100)
Имя входного файла:
INPUT.TXT
Имя выходного файла:
OUTPUT.TXT
Максимальное время работы на одном тесте:
1 секунда
Максимальный объем используемой памяти:
64 мегабайта
Король Нетландии решил вырубить некоторые деревья, растущие перед его дворцом.
Деревья перед дворцом короля посажены в ряд, всего там растет N деревьев, расстояния
между соседними деревьями одинаковы.
После вырубки перед дворцом должно остаться M деревьев, и расстояния между
соседними деревьями должны быть одинаковыми. Помогите королю выяснить, сколько
существует способов вырубки деревьев.
Требуется написать программу, которая по заданным числам N и M определит, сколько
существует способов вырубки некоторых из N деревьев так, чтобы после вырубки в саду
осталось M деревьев и соседние деревья находились на равном расстоянии друг от друга.
Министерство образования и науки Республики Хакасия
Муниципальный этап ВсОШ по информатике 2014-2015 учебный год
Формат входных данных
Входной файл INPUT.TXT содержит два целых числа M и N(0 <= M <= N <= 1000).
Формат выходных данных
В выходном файле OUTPUT.TXT должно содержаться одно число - искомое количество
способов.
Пример входных и выходных данных
INPUT.TXT
OUTPUT.TXT
53
4
Разбор задачи:
Зафиксируем расстояние между деревьями после вырубки. Если оно равно d, то
возможно n – d(m – 1) – m + 1 способов вырубить деревья. Суммируя по всем d, получаем
ответ. Если у нас есть 0 деревьев и 0 деревьев должно остаться после вырубки, то
существует один вариант вырубки - это надо учитывать при решении задачи.
Вариант 1 (с использованием цикла)
var
n, m : longint;
i, d, s : longint;
input, output: text;
begin
Assign(input,'input.txt');
Reset(input);
Assign(output,'output.txt');
Rewrite(output);
Read(input,n,m);
s := 0;
if m = 0 then
s := 1
else
if m = 1 then
s := n
else
for d := 1 to (n-1) div (m-1) do
inc(s,n-(m-1)*d);
Write(output,s);
Close(input);
Close(output);
end.
Вариант 2 (без цикла)
var
n, m ,k: longint;
i, d, s : longint;
input, output: text;
begin
Assign(input,'input.txt');
Reset(input);
Assign(output,'output.txt');
Rewrite(output);
read(input,n,m);
if m=0 then
s:=1
Министерство образования и науки Республики Хакасия
Муниципальный этап ВсОШ по информатике 2014-2015 учебный год
else
if m=1 then
s:=n
else
begin
k:=(n-1) div (m-1);{количество членов прогрессии}
d:=m-1;{шаг прогрессии}
s:=(2+(k-1)*d)*k div 2;{формула суммы первых членов арифметической прогрессии}
end;
write(output, s);
Close(input);
Close(output);
end.
Задача 3. Клавиши клавиатуры (Время: 2 сек. Память: 16 Мб Баллы: 100)
Имя входного файла:
INPUT.TXT
Имя выходного файла:
OUTPUT.TXT
Максимальное время работы на одном тесте:
2 секунды
Максимальный объем используемой памяти:
64 мегабайта
Всем известно, что со временем клавиатура изнашивается, и клавиши на ней начинают
залипать. Конечно, некоторое время такую клавиатуру еще можно использовать, но для
нажатий клавиш приходиться использовать большую силу. При изготовлении клавиатуры
изначально для каждой клавиши задается количество нажатий, которое она должна
выдерживать. Если знать эти величины для используемой клавиатуры, то для определенной
последовательности нажатых клавиш можно определить, какие клавиши в процессе их
использования сломаются, а какие – нет.
Требуется написать программу, определяющую, какие клавиши сломаются в процессе
заданного варианта эксплуатации клавиатуры.
Формат входных данных
Первая строка входного файла содержит целое число n (1 ≤ n ≤ 100) – количество клавиш
на клавиатуре. Вторая строка содержит n целых чисел – с1, с2, … , сn, где сi (1 ≤ сi ≤ 100000) –
количество нажатий, выдерживаемых i-ой клавишей. Третья строка содержит целое число k
(1 ≤ k ≤ 100000) – общее количество нажатий клавиш, и последняя строка содержит k целых
чисел pj (1 ≤ pj ≤ n) – последовательность нажатых клавиш.
Формат выходных данных
В выходной файл необходимо вывести n строк, содержащих информацию об исправности
клавиш. Если i-ая клавиша сломалась, то i-ая строка должна содержать слово “yes” (без
кавычек), если же клавиша работоспособна – слово “no”.
Пример входных и выходных данных
INPUT.TXT
OUTPUT.TXT
5
yes
1 50 3 4 3
no
16
no
1234513345555545
no
yes
Разбор задачи:
Решение данной задачи не представляет особых сложностей и заключается в
следующем. В первую очередь необходимо для каждой клавиши на клавиатуре посчитать
Министерство образования и науки Республики Хакасия
Муниципальный этап ВсОШ по информатике 2014-2015 учебный год
количество нажатий на нее и проверить, больше ли оно некоторого числа. Количество
нажатий клавиш можно хранить в массиве и, считывая очередное нажатие, увеличивать
счетчик для данной клавиши. После считывания всех нажатий для всех клавиш следует
последовательно проверить выполнение указанного в описании задачи условие.
Программная реализация решения этой задачи требует аккуратности при чтении
входных данных и при выводе выходных данных. Кроме этого, требуется аккуратно
организовать хранение информации о числе нажатий в одномерном массиве. Таким образом,
чтобы набрать полный балл, требуется реализовать простейшее линейное решение, в
котором используются лишь базовые операции с массивами.
Возможные ошибки
При решении задачи надо обратить внимание, что в выходной файл данные надо
выводить в нижнем регистре.
Текст программы на Паскале:
Var
c :array [1..100] oflongint;
n, i, k, t : longint;
f : text;
Begin
Assign(f,'keyboard.in');
Reset(f);
ReadLn(f,n);
For i:=1 to N do
Read(f,c[i]);
Readln(f,k);
For i:=1 to k do
begin
Read(f,t);
Dec(c[t]);
end;
Close(f);
Assign(f,'keyboard.out');
Rewrite(f);
For i:=1 to N do
If c[i]>=0 Then
Writeln(f,'no')
ElseWriteln(f,'yes');
Close(f);
End.
Задача 4. Газон (Время: 2 сек. Память: 16 Мб Баллы: 100)
Имя входного файла:
INPUT.TXT
Имя выходного файла:
OUTPUT.TXT
Максимальное время работы на одном тесте:
2 секунды
Максимальный объем используемой памяти:
64 мегабайта
Фермер Иван с юности следит за своим газоном. Газон можно считать плоскостью, на которой
в каждой точке с целыми координатами растет один пучок травы. В одно из воскресений Иван
воспользовался газонокосилкой и постриг некоторый прямоугольный участок газона. Стороны
этого участка параллельны осям координат, а две противоположные вершины расположены в
точках (x1, y1) и (x2, y2). Следует отметить, что пучки травы, находящиеся на границе этого
Министерство образования и науки Республики Хакасия
Муниципальный этап ВсОШ по информатике 2014-2015 учебный год
прямоугольника, также были пострижены. Довольный результатом Иван купил и установил на
газоне дождевальную установку. Она была размещена в точке с координатами (x3, y3) и имела
радиус действия струи r. Таким образом, установка начала поливать все пучки, расстояние от
которых до точки (x3, y3) не превышало r. Все было хорошо, но Ивана заинтересовал
следующий вопрос: сколько пучков травы оказалось и пострижено, и полито в это
воскресенье?
Требуется написать программу, которая позволит дать ответ на вопрос Ивана.
Формат входных данных
В первой строке входного файла содержатся четыре целых числа x1, y1, x2, y2
(−100 000 ≤ x1 < x2 ≤ 100 000; −100 000 ≤ y1 < y2 ≤ 100 000).
Во второй строке входного файла содержатся три целых числа x3, y3, r
(−100 000 ≤ x3, y3 ≤ 100 000; 1 ≤ r ≤ 100 000)
Формат выходных данных
В выходной файл необходимо вывести одно целое число — число пучков травы, которые
были и пострижены, и политы.
Пример входных и выходных данных
INPUT.TXT
OUTPUT.TXT
0054
14
403
Иллюстрация к примеру
Разбор задачи:
Одно из возможных решений данной задачи заключается в следующем. Для каждой
прямой, содержащей все пучки травы с равной координатой по оси абсцисс (аналогично
можно рассматривать и ось ординат), найдем ее точки пересечения с окружностью,
отображающей область действия поливальной установки, если, конечно, такие точки
существуют. Получив данные точки, не сложно за время O(1) посчитать количество пучков
травы на данной прямой одновременно и политых, и постриженных. Это делается с
помощью операции вычисления целой части числа. Далее, просуммировав найденные числа
для всех прямых, можно найти ответ на поставленную задачу.
Не сложно показать, что время работы рассматриваемого решения будет O(r).
Текст программы на Паскале:
type
abc=Int64;
var
x1,y1,x2,y2,x3,y3,x: longint;
k,r,y : abc;
input,output: text;
functionkol(x,z1,z2:longint):longint;
Министерство образования и науки Республики Хакасия
Муниципальный этап ВсОШ по информатике 2014-2015 учебный год
var
min,max,k: longint;
begin
if (x<x1)or(x>x2)or(z1>y2)or(z2<y1) then
k:=0
else
begin
min:=y1;
if z1>y1 then
min:=z1;
max:=y2;
if z2<y2 then
max:=z2;
k:=max-min+1
end;
kol:=k
end;
begin
assign(input, 'input.txt');
reset(input);
assign(output, 'output.txt');
rewrite(output);
readln(input,x1,y1,x2,y2);
read(input,x3,y3,r);
k:=kol(x3,y3-r,y3+r);
y:=r;
for x:=1 to r-1 do
begin
whilesqr(x)+sqr(y)>sqr(r) do
y:=y-1;
k:=k+kol(x3+x,y3-y,y3+y)+kol(x3-x,y3-y,y3+y)
end;
k:=k+kol(x3+r,y3,y3)+kol(x3-r,y3,y3);
write(output,k);
close(input);
close(output);
end.
Задача 5. Эскалатор в метро (Время: 2 сек. Память: 16 Мб Баллы: 100)
Станция метрополитена оснащена эскалатором. Пусть N человек бегут вниз по
эскалатору, причем i-ый пробегает одну ступеньку за ti секунд. По технике безопасности бега
по эскалатору, на эскалаторе запрещены «обгоны», то есть если человек A в процессе бега
догнал человека B, который бежит с более низкой скоростью, то далее, до конца эскалатора,
человек A бежит со скоростью человека B. Однако ступени эскалатора таковы, что на них
может помещаться несколько человек одновременно.
Ваша задача написать программу, которая поможет работникам станции рассчитать, когда
закончит свой бег по эскалатору каждый бегущий человек.
Входные данные
В первой строке входного файла INPUT.TXT записано число N (1 ≤ N ≤ 10 5). В
следующих N строках перечислены пары чисел ti, wi (1 ≤ ti, wi ≤ 106) – время пробега одной
Министерство образования и науки Республики Хакасия
Муниципальный этап ВсОШ по информатике 2014-2015 учебный год
ступени и количество ступеней до конца эскалатора для i-го человека. Гарантируется, что
изначально всем людям осталось бежать различное число ступеней.
Выходные данные
В i-ой строке выходного файла OUTPUT.TXT выведите время в секундах, через которое iый человек сойдет с эскалатора.
Пример
№
INPUT.TXT
OUTPUT.TXT
3
20
2 10
33
1
3 11
33
1 12
Разбор задачи:
Так как на эскалаторе нельзя обгонять, то расположим всех людей в порядке увеличения
стартовой ступеньки. Это можно сделать с помощью алгоритма сортировки. Количество
людей достаточно велико, поэтому квадратичные алгоритмы не подходят для этой задачи.
ВС++ можно воспользоваться стандартной библиотекой шаблонов и применить процедуру
sort. В Паскале же придётся написать быструю сортировку Хоара (или любой другой
алгоритм сортировки с асимптотикой времени работы не хуже O ( NlogN ) )
самостоятельно.
Заметим, что нет необходимости сортировать сами данные. Можно завести ещё один массив с
номерами людей и сортировать его. То есть расположить номера людей в порядке
возрастания стартовой ступеньки (такой вариант реализован в решении на Паскале). Если бы
на эскалаторе был только i -ый человек, то его время прибытия было равно ti⋅wi. Но у него
есть помеха – тот, кто идёт перед ним. Тогда итоговое время будет Ti =max{ Ti −1, ti⋅wi} . И
рассматривать людей следует снизу вверх. Осталось дело за малым – вести полученные
результаты в нужном порядке. В решении на С++ снова применяется сортировка, а на Паскале
(так как менялись номера людей, а не сами данные) всё выводится по порядку.
Решение на языке Паскаль
usesmath;
var
n,i : Longint;
mm : array [0..100500,0..1] of Longint;
tmp : Int64;
res : array [0..100500] of Int64;
m : array [0..100500] of Longint;
procedureqs(l,r : Longint);
var
i,j,x,t : Longint;
begin
i :=l;
j :=r;
x :=mm[m[l +random(r-l)], 1];
repeat
while mm[m[i], 1] <x doinc(i);
while mm[m[j], 1] >x dodec(j);
ifi<=j then begin
t :=m[i];
m[i] :=m[j];
m[j] :=t;
inc(i);
Министерство образования и науки Республики Хакасия
Муниципальный этап ВсОШ по информатике 2014-2015 учебный год
dec(j);
end;
untili>j;
if l <j thenqs(l,j);
if r >ithenqs(i,r);
end;
begin
randomize;
assign(input, 'input.txt');reset(input);
assign(output, 'output.txt');rewrite(output);
Read(n);
tmp := 1;
fori:=0 to n-1 do begin
Read(mm[i, 0],mm[i, 1]);
m[i] :=i;
res[i] :=tmp *mm[i, 0] *mm[i, 1];
end;
qs(0,n-1);
fori:=1 to n-1 do
res[m[i]] :=max(res[m[i]],res[m[i-1]]);
fori:=0 to n-1 doWriteLn(res[i]);
end.
Download