search icon search icon ВЕРСИЯ ДЛЯ СЛАБОВИДЯЩИХ

Предметный тур. Информатика. 3 этап

Информатика. 8–11 классы
Задача 1.1.(10 баллов)
Раздел царства
Тема: интегральные суммы

Имя входного файла: стандартный ввод или input.txt.

Имя выходного файла: стандартный вывод или output.txt.

Ограничение по времени выполнения программы: 2 с.

Ограничение по памяти: 64 Мбайт.

Условие

Победил Иван Змея Горыныча и пришел за наградой. Свадьбу с Царевной сразу сыграли, а вот как полцарства в придачу выделить — стали думать.

Царство задано прямоугольной матрицей, в каждой ячейке которой указано количество сторожевых башен. Разделить царство можно только по прямой, при этом прямая должна быть строго вертикальной или горизонтальной.

Помогите разделить царство на две части так, чтобы количество сторожевых башен в каждой из частей было одинаковым, или сообщите, что это невозможно.

Формат входных данных

В первой строке содержатся два числа: \(N, M\) (\(1 \leqslant N, M \leqslant 1000\)) — ширина и высота царства.

В последующих \(N\) строках содержатся \(M\) чисел \(d_{ij}\) через пробел (\(0 \leqslant d_{ij} \leqslant 10^8\)) — количество башен в данной части царства.

Формат выходных данных

Если царство можно разделить горизонтально (независимо от того, можно ли его разделить вертикально), в ответ выведите символ \(h\) и число \(i\) — номер последней строки матрицы, принадлежащей верхнему полцарству (если подходящих \(i\) несколько — выведите минимальный).

Если царство нельзя разделить горизонтально, но можно разделить вертикально, в ответ выведите символ \(\nu\) и число \(j\) — номер последнего столбца матрицы, принадлежащей левому полцарству (если подходящих \(j\) несколько — выведите минимальный).

Если царство нельзя разделить поровну на два полцарства, в ответ выведите indivisible.

Тестовые данные

Номер тестаСтандартный вводСтандартный вывод
1
3 4
1 1 1 3
1 1 1 2
1 1 1 4
v3
2
2 2
1 1
1 9
indivisible

Примечания

В первом примере можно разделить царство вертикальной чертой после третьего столбца (суммы башен будут равны 9).

Во втором примере нет возможного разбиения.

Пример программы-решения

Ниже представлено решение на языке Python.

Python
def solution(n, m, kingdom):
    add_kingdom = []
    for i in range(n):
        add_kingdom.append([])
        for j in range(m):
            if i == 0:
                if j == 0:
                    add_kingdom[i].append(kingdom[i][j])
                else:
                    add_kingdom[i].append(add_kingdom[i][j - 1] + kingdom[i][j])
            else:
                if j == 0:
                    add_kingdom[i].append(add_kingdom[i - 1][j] + kingdom[i][j])
                else:
                    add_kingdom[i].append(add_kingdom[i - 1][j] + add_kingdom[i][j - 1] -
                                          add_kingdom[i - 1][j - 1] + kingdom[i][j])
 
    for i in range(n):
        if add_kingdom[i][m - 1] * 2 == add_kingdom[n - 1][m - 1]:
            return 'h' + str(i + 1)
 
    for j in range(m):
        if add_kingdom[n - 1][j] * 2 == add_kingdom[n - 1][m - 1]:
            return 'v' + str(j + 1)
 
    return 'indivisible'
 

n, m = [int(x) for x in input().split()]
kingdom = []
for _ in range(n):
    kingdom.append([int(x) for x in input().split()])
 
print(solution(n, m, kingdom))
Задача 1.2.(15 баллов)
Змеи и лестницы
Темы: обход графа в глубину, DFS

Имя входного файла: стандартный ввод или input.txt.

Имя выходного файла: стандартный вывод или output.txt.

Ограничение по времени выполнения программы: 2 с.

Ограничение по памяти: 64 Мбайт.

Условие

Представлена разновидность настольной игры «Змеи и лестницы».

Фишка начинает движение в клетке «старт» (номер клетки 0) и двигается в сторону клетки «финиш» (номер клетки \(N\)), где поле представляет собой \(N+1\) клеток, пронумерованных от 0 до \(N\) с шагом 1. Движение происходит по ходам, где ход — это бросок шестигранного кубика и перемещение фишки (в соответствии с тем, какая цифра выпадает на кубике — на столько клеток вперед продвигается фишка).

При этом на поле есть специальные пары клеток:

  • лестницы — задаются форматом \(i\) \(j\), где \(i < j\); при попадании на клетку \(i\) фишка немедленно (не тратя хода) перемещается на клетку \(j\);
  • змеи — задаются форматом \(i\) \(j\), где \(i > j\); при попадании на клетку \(i\) фишка немедленно (не тратя хода) перемещается на клетку \(j\).

Каждый тест в задаче представляет собой вопрос: можно ли при удачных1 бросках кубика пройти игру за указанное количество ходов или менее, и если можно — то за какое?

Формат входных данных

В первой строке через пробел заданы три целых числа \(N\) — порядковый номер клетки финиша (\(1 \leqslant N \leqslant 10^5\)), \(M\) — количество специальных пар клеток: лестниц или змей (\(0 \leqslant M \leqslant \dfrac{N}{2}\)), \(T\) — предел количества ходов, доступных в данной игре (\(1 \leqslant T \leqslant 10^6\)).

В дальнейших \(M\) строках через пробел содержатся по два числа \(i\) \(j\) — описание лестницы или змеи (\(1 \leqslant i, j \leqslant N-1\)).

Гарантируется, что если пара клеток \(i\) \(j\) — лестница или змея, то ни одной другой лестницы или змеи не начинается и не заканчивается в клетках \(i\) \(j\).

Формат выходных данных

Если есть возможность пройти из старта на финиш за менее, чем \(T\) ходов — выведите минимально возможное количество ходов, иначе выведите (\(-1\)).

Тестовые данные

Номер тестаСтандартный вводСтандартный вывод
1
12 2 5
6 3
1 7
2
2
12 1 5
6 3
3
3
30 1 4
10 1
-1

Примечания

В примере 1 можно достигнуть финиша (клетки 12) за два хода: бросок 1 (из клетки 1 перемещаемся в клетку 7) + бросок 5 (\(7 + 5 = 12\)).

В примере 2 можно достигнуть финиша (клетки 12) за три хода, например, один из способов: бросок 1 + бросок 6 + бросок 5 (заметим, что за 2 хода — бросок 6 + бросок 6 — игру нельзя закончить, так как при первом броске 6 переместимся в клетку 3).

В примере 3 за четыре хода игру закончить нельзя.

Пример программы-решения

Ниже представлено решение на языке Python.

Python
def can_move(step, finish):
    if step <= finish:
        return True
    return False
 
def solution(finish, snakes, limit):
    next_points = [[0, 1]]
    counter = 0
    moves = [0] + [limit + 1] * finish
 
    while len(next_points) > counter:
        p0 = next_points[counter][0]
        iterate = next_points[counter][1]
 
        turn = [0, 1, 1, 1, 1, 1, 1, 0]
        for dice in range(6):
            if can_move(p0 + dice + 1, finish):
                if p0 + dice + 1 in snakes.keys():
                    turn[dice + 1] = 2
            else:
                turn[dice + 1] = 0
        for dice in range(6):
            if turn[dice + 1] == 2:
                if moves[p0 + dice + 1] > iterate:
                    moves[p0 + dice + 1] = iterate
                    moves[snakes[p0 + dice + 1]] = iterate
                    next_points.append([snakes[p0 + dice + 1], iterate + 1])
            elif turn[dice + 1] > 0:
                if moves[p0 + dice + 1] > iterate:
                    moves[p0 + dice + 1] = iterate
                    next_points.append([p0 + dice + 1, iterate + 1])
        counter += 1
 
    if moves[-1] <= limit:
        return moves[-1]
    else:
        return -1
 

finish, n_snakes, turn = [int(x) for x in input().split()]
card = {}
for _ in range(n_snakes):
    p1, p2 = [int(x) for x in input().split()]
    card[p1] = p2
 
print(solution(finish, card, turn))
Задача 1.3.(20 баллов)
Остров сокровищ
Тема: бинарный поиск

Имя входного файла: стандартный ввод или input.txt.

Имя выходного файла: стандартный вывод или output.txt.

Ограничение по времени выполнения программы: 2 с.

Ограничение по памяти: 64 Мбайт.

Условие

Знаменитый пират Джон Сильвер только что вручил участникам карту Острова сокровищ. Но где конкретно Джон зарыл клад — на карте не указано, и Джон предлагает это угадать!

Карта представляет собой квадратную матрицу размером \(N\times N\) клеток. По верхней и левой границе проставлена нумерация столбца и строки соответственно, начинающаяся с нуля (то есть верхняя левая клетка имеет координату 0, 0).

Клад зарыт в одной из клеток карты, и Джон дает участникам 15 попыток угадать, в какой именно!

Протокол взаимодействия

На первом шаге сообщается \(N\) — размер карты.

Далее участники могут предположить координату, в которой зарыт клад, на что будут получены в ответ 2 символа:

  • Первый символ: S — если клад строго южнее (больше) предположенной координаты (south), или N — если координата клада севернее (меньше) или равна предположенной (north).
  • Второй символ: E — если клад строго восточнее (больше) предположенной координаты (east), или W — если координата клада западнее (меньше) или равна предположенной (west).

Если координата клада определена, необходимо дать окончательный ответ.

Формат входных данных

Используйте стандартный ввод для чтения размеров карты и ответов на предположения.

В первой строке содержится число \(N\) — размеры карты (\(1 \leqslant N \leqslant 10^4\)).

После отправки предположения в ответе будет содержаться строка из двух символов \(x_1x_2\), каждый из которых равен одной из заглавных букв: S, N, E, W.

После отправки окончательного ответа в ответ будет получена строка success — если координата клада угадана верно, или failed — в обратном случае.

Формат выходных данных

Используйте стандартный вывод для взаимодействия, при этом укажите параметр flush=True.

Для отправки предположения выведите через пробел второй координаты \(x\) и \(y\) — предполагаемую позицию клада.

Для отправки окончательного ответа выведите через пробел символ восклицательный знак ! и \(x\) и \(y\) — окончательные координаты клада.

Примечания

Рис. 1.1.

Рассмотрим пример взаимодействия для карты, изображенной на рис. 1.1:

  • Ввод: 3
  • Вывод: 0 0
  • Ввод: SW
  • Вывод: 1 0
  • Ввод: NW
  • Вывод: 2 0
  • Ввод: NW
  • Вывод: 0 1
  • Ввод: SW
  • Вывод: 1 1
  • Ввод: NW
  • Вывод: 2 1
  • Ввод: NW
  • Вывод: ! 1 0
  • Ввод: success

Расшифровка:

  • На первом шаге получаем размер карты: 3 на 3.
  • Предполагаем, что клад в клетке 0, 0.
  • Получаем ответ, что он на юго-западе.
  • Предполагаем, что клад в клетке 1, 0.
  • Получаем ответ, что он на северо-западе. и т. д.
  • Даем окончательный ответ, что клад в клетке 1, 0.
  • Получаем успешный ответ.

Пример программы-решения

Ниже представлено решение на языке Python.

Python
def calculate(pa, a, fa):
    res = ''
    if fa == 0:
        if pa[0] < a[1]:
            res += 'S'
        else:
            res += 'N'
 
        if pa[1] < a[2]:
            res += 'E'
        else:
            res += 'W'
 
    return res
 

map_size = int(input())
row_num = [0, map_size - 1]
col_num = [0, map_size - 1]
counter = 0
 
while row_num[0] != row_num[1] or col_num[0] != col_num[1]:
    counter += 1
    p1, p2 = (row_num[0] + row_num[1]) // 2, (col_num[0] + col_num[1]) // 2
    print(p1, p2, flush=True)
    direction = input()
    if direction[0] == 'S':
        row_num[0] = p1 + 1
    else:
        row_num[1] = p1
 
    if direction[1] == 'E':
        col_num[0] = p2 + 1
    else:
        col_num[1] = p2
 
print('!', row_num[0], col_num[0])
Задача 1.4.(25 баллов)
Базовое число
Темы: математика, жадные алгоритмы

Имя входного файла: стандартный ввод или input.txt.

Имя выходного файла: стандартный вывод или output.txt.

Ограничение по времени выполнения программы: 2 с.

Ограничение по памяти: 64 Мбайт.

Условие

Дано базовое число \(N\). На очередной итерации будет получено еще одно целое число \(m\), и можно сделать одну из трех операций:

  • \(N + m\);
  • \(N - m\);
  • \(N \cdot m\).

После чего результат операции становится новым базовым числом (иными словами, операции между итерациями происходят последовательно, без учета приоритета умножения).

Рассчитайте, какое максимально возможное базовое число можно получить.

Формат входных данных

В первой строке через пробел заданы два целых числа \(M\) — количество чисел \(m\) (\(1 \leqslant M \leqslant 5\cdot 10^4\)), \(N\) — базовое число (\(-10 \leqslant N \leqslant 10\)).

В дальнейших \(M\) строках содержатся числа \(m\) (\(-10 \leqslant m \leqslant 10\)).

Формат выходных данных

В связи с тем, что максимально возможное базовое число будет большим, выведите только его остаток от деления на \(10^{10}\) (то есть если ответ — это число 123456789012345, выведите только 6789012345).

Тестовые данные

Номер тестаСтандартный вводСтандартный вывод
1
3 1
1
2
3
12
2
3 7
0
-2
2
18

Примечания

В примере 1 максимально возможное базовое число получается так: \(1 + 1 = 2 + 2 = 4 \cdot 3 = 12\).

В примере 2: \(7- 0 = 7- (-2) = 9 \cdot 2 = 18\).

Пример программы-решения

Ниже представлено решение на языке Python.

Python
def solution(n1, nums):
div = 10 ** 10
my_min = n1
my_max = n1
for x in nums:
        new_min = min(my_min + x, my_min - x, my_min * x, my_max + x, my_max - x, my_max * x)
        new_max = max(my_min + x, my_min - x, my_min * x, my_max + x, my_max - x, my_max * x)
        my_min, my_max = new_min, new_max
 
return my_max % div
 
n, num1 = [int(x) for x in input().split()]
numbers = []
for i in range(n):
numbers.append(int(input()))
print(solution(num1, numbers))
Задача 1.5.(30 баллов)
Автобусное государство
Темы: динамическое программирование, DFS

Имя входного файла: стандартный ввод или input.txt.

Имя выходного файла: стандартный вывод или output.txt.

Ограничение по времени выполнения программы: 2 с.

Ограничение по памяти: 64 Мбайт.

Условие

Добро пожаловать в Автобусное государство!

Оно названо так потому, что кататься на автобусах в нем можно совершенно бесплатно. При этом помимо автобусов, в государстве ходят поезда — они в два раза быстрее автобусов, но на поезд необходимо приобретать билет, стоимость которого зависит от расстояния.

Государство представляет собой неориентированный взвешенный граф, где города — это вершины графа, а существующие дороги заданы ребрами. Вес ребер — это длительность перемещения между двумя городами на автобусе (гарантируется, что вес — всегда четное число). Если существует ребро между городами \(I\) и \(J\) с весом \(w\), значит, между городами переместиться можно как бесплатно на автобусе за время \(w\), так и платно на поезде за время \(\displaystyle\frac{w}{2}\), потратив при этом \(w\) монет (при этом билет необходимо оплатить полностью).

Задача: добраться из города \(S\) в город \(F\) как можно быстрее, имея \(M\) монет.

Формат входных данных

В первой строке через пробел заданы три целых числа \(S\) — номер вершины стартового города (\(1 \leqslant S \leqslant 10^3\)), \(F\) — номер вершины конечного города (\(1 \leqslant F \leqslant 10^3\)), \(M\) — стартовое количество монет (\(0 \leqslant M \leqslant 10^3\)).

Во второй строке задано число \(N\) — количество дорог в государстве (\(1 \leqslant F \leqslant 5 \cdot 10^3\)).

В дальнейших \(N\) строках содержатся описания дорог в формате \(I\)–\(J\) \(w\) (\(1 \leqslant I, J \leqslant 10^3\), \(2 \leqslant w \leqslant 10^5\)).

Формат выходных данных

В ответ выведите единственное число — минимальную длительность перемещения из города \(S\) в город \(F\) (гарантируется, что путь существует).

Тестовые данные

Номер тестаСтандартный вводСтандартный вывод
1
1 7 18
8
1-2 2
1-3 2
2-4 20
3-5 12
3-6 22
4-7 2
5-6 12
6-7 2
20
2
1 7 0
8
1-2 2
1-3 2
2-4 20
3-5 12
3-6 22
4-7 2
5-6 12
6-7 2
24

Примечания

На рис. 1.2 указан граф из примеров №№ 1 и 2.

Очевидно, что при наличии 18 монет в примере № 1 наиболее выгодным маршрутом будет: \(1-3-5-6-7\) (где участки \(1-3\), \(3-5\), \(6-7\) проедем на поезде, потратив \(2+12+2=16\) монет и сократив время на 8). Тогда суммарное время будет равно: \(1+6+12+1=20\).

Рис. 1.2.

В примере № 2 у участников нет монет, поэтому все маршруты нужно проезжать на автобусах, следовательно, наиболее выгодным маршрутом будет: \(1-2-4-7\). Тогда суммарное время будет равно: \(2+20+2=24\).

Пример программы-решения

Ниже представлено решение на языке Python.

Python
import heapq

def solution(s, f, m, r):
    distances = {point: 10 ** 10 for point in r}
    distances[s] = 0
    cost_matrix = [[0] * (m + 1)]
    drive = [(0, s, cost_matrix, 0)]

    while drive:
        current_distance, current_point, cost_matrix, points_in_road = heapq.heappop(drive)
        # print(current_distance, current_point, cost_matrix, points_in_road)
        if current_point == f:
            return current_distance
 
        if current_distance > distances[current_point]:
            continue
 
        for neighbor, road_len in r[current_point]:
            current_cost = cost_matrix[:]
            current_cost.append([])
            time_win = road_len // 2
            for j in range(m + 1):
                if road_len > j:
                    current_cost[points_in_road + 1].append(current_cost[points_in_road][j])
                else:
                    current_cost[points_in_road + 1].append(
                        max(current_cost[points_in_road][j], current_cost[points_in_road][j - road_len] + time_win))
 
            new_discount = current_cost[points_in_road + 1][m] - current_cost[points_in_road][m]
            distance = current_distance + road_len - new_discount
 
            if distance < distances[neighbor]:
                distances[neighbor] = distance
                heapq.heappush(drive, (distance, neighbor, current_cost, points_in_road + 1))
 
    return -1
 
start, finish, money = [int(x) for x in input().split()]
roads = int(input())
road_map = {}
for _ in range(roads):
    road = input().split()
    p1, p2 = [int(x) for x in road[0].split("-")]
    cost = int(road[1])
    if p1 not in road_map.keys():
        road_map[p1] = [[p2, cost]]
    else:
        road_map[p1].append([p2, cost])
    if p2 not in road_map.keys():
        road_map[p2] = [[p1, cost]]
    else:
        road_map[p2].append([p1, cost])
 
print(solution(start, finish, money, road_map))

  1. Считаем, что можно выбирать любую грань кубика для очередного хода вместо броска.↩︎
text slider background image text slider background image
text slider background image text slider background image text slider background image text slider background image