Тема 26. Обработка целочисленной информации с использованием сортировки

26.05 Поиск мест на поле (билеты, саженцы, матрицы)

Вспоминай формулы по каждой теме
Решай новые задачи каждый день
Вдумчиво разбирай решения
ШКОЛКОВО.
Готовиться с нами - ЛЕГКО!
Подтемы раздела обработка целочисленной информации с использованием сортировки
Решаем задачи

Ошибка.
Попробуйте повторить позже

Задача 21#85887Максимум баллов за задание: 2

При проведении эксперимента заряженные частицы попадают на чувствительный экран, представляющий из себя матрицу размером 10000  на 10000  точек. При попадании каждой частицы на экран в протоколе фиксируются координаты попадания: номер ряда (целое число от 1  до 10000  ) и номер позиции в ряду (целое число от 1  до 10000  ). Точка экрана, в которую попала хотя бы одна частица, считается светлой, точка, в которую ни одна частица не попала — тёмной. При анализе результатов эксперимента рассматривают группы светлых точек, расположенных в одном ряду подряд, то есть без тёмных точек между ними. Вам необходимо по заданному протоколу определить максимальную длину такой группы и номер ряда, в котором эта группа встречается. Если таких рядов несколько, укажите минимально возможный номер.

Входные данные

Первая строка входного файла содержит целое число N  — общее количество частиц, попавших на экран. Каждая из следующих N  строк содержит 2  целых числа: номер ряда и номер позиции в ряду.

Выходные данные

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

Вложения к задаче
Показать ответ и решение

Решение (Excel/LibreOffice)

Сначала перенесем данные из файла в Excel, скопировав и вставив с разделителем пробел, а также удалим первую строчку.

Настраиваемой сортировкой отсортируем в первую очередь по столбцу A  по возрастанию, во вторую - по столбцу B  по возрастанию.

PIC

PIC

Выделим полностью столбцы A  и B  , перейдём в раздел Данные и нажимаем на инструмент Удалить дубликаты, в появившемся окне выбираем Выделить все и нажимаем ОК (это удалит пиксели, в которые частицы попрали несколько раз).

В LibreOffice Calc необходимо также выделить оба столбца, применить фильтр и перейти в раздел Фильтр по условию -> Стандартный фильтр.

В условиях фильтра необходимо через И выбрать столбцы A  и B  , установить значение Не пусто и поставить галочку напротив Без повторений. После чего нужно скопировать отфильтрованные значения на новый лист и работать уже там.

PIC

PIC

Чтобы определить самую длинную линию, в ячейку C1  запиешем 1, а в ячейку C2  запишем и растянем до конца таблицы следующую формулу:

=ЕСЛИ(И(A2=A1;B2-B1=1);C1+1;1)

Отфильтруем данные по столбцу C  , убрав все нули, единицы и двойки, и получим места, для которых выполнилось условие. Значения из столбцов C  и A  для самой большой величины в столбце C  запишем в ответ.

Решение (Python)

f = open(’m6_26_18_04__3u8y8.txt’)
n = map(int, f.readline().split())
# Сортировка по ряду и номеру пикселя
a = sorted([list(map(int, i.split())) for i in f])
l_max = 0; l = 1; num_r = -1
for i in range(1, len(a)-1):
    # Если номер ряда совпадает и пиксели соседние увеличиваем счетчик
    if (a[i][0] == a[i+1][0]) and (a[i+1][1]-a[i][1] == 1):
        l += 1
    # Если нет, то обновляем максимум и обнуляем счетчик
    else:
        if l > l_max:
            l_max = l
            num_r = a[i][0]
        l = 1
if l > l_max:
    l_max = l
    num_r = a[-1][0]
print(l_max, num_r)

Ответ: 13 2513

Ошибка.
Попробуйте повторить позже

Задача 22#85888Максимум баллов за задание: 2

При проведении эксперимента заряженные частицы попадают на чувствительный экран, представляющий из себя матрицу размером 10000  на 10000  точек. При попадании каждой частицы на экран в протоколе фиксируются координаты попадания: номер ряда (целое число от 1  до 10000  ) и номер позиции в ряду (целое число от 1  до 10000  ). Точка экрана, в которую попала хотя бы одна частица, считается светлой, точка, в которую ни одна частица не попала — тёмной. При анализе результатов эксперимента рассматривают ряды, в которых и первая и последняя точка светлые. Вам необходимо по заданному протоколу определить максимальное количество точек в таком ряду.

Входные данные

Первая строка входного файла содержит целое число N  — общее количество частиц, попавших на экран. Каждая из следующих N  строк содержит 2  целых числа: номер ряда и номер позиции в ряду.

Выходные данные

В ответе запишите два целых числа: сначала максимальное количество светлых точек в подходящем ряду, затем – номер ряда, в котором встречается такое количество точек.

Вложения к задаче
Показать ответ и решение

Решение (Excel/LibreOffice)

Сначала перенесем данные из файла в Excel, скопировав и вставив с разделителем пробел, а также удалим первую строчку.

Настраиваемой сортировкой отсортируем в первую очередь по столбцу A  по возрастанию, во вторую - по столбцу B  по возрастанию.

PIC

PIC

Выделим полностью столбцы A  и B  , перейдём в раздел Данные и нажимаем на инструмент Удалить дубликаты, в появившемся окне выбираем Выделить все и нажимаем ОК (это удалит деревья, которые были по ошибке сняты дважды).

В LibreOffice Calc необходимо также выделить оба столбца, применить фильтр и перейти в раздел Фильтр по условию -> Стандартный фильтр.

В условиях фильтра необходимо через И выбрать столбцы A  и B  , установить значение Не пусто и поставить галочку напротив Без повторений. После чего нужно скопировать отфильтрованные значения на новый лист и работать уже там.

PIC

PIC

Чтобы определить самую длинную линию, в ячейку C1  запиешем ”нет”, а в ячейку C2  запишем и растянем до конца таблицы следующую формулу:

=ЕСЛИ(A2=A1;C1;ЕСЛИ(B2=1;”да”;”нет”))

Таким образом ”да” проставится для рядов, начинающихся со светлой точки. В ячейку D1  запишем 1, а в ячейку D2  запишем и растянем до конца таблицы следующую формулу:

=ЕСЛИ(A2=A1;D1+1;1)

С её помощью мы посчитаем количество точек в каждом ряду. В ячейку E1  запишем и растянем до конца таблицы следующую формулу:

=ЕСЛИ(И(A1<>A2;C1=”да”;B1=10000);1;0)

С помощью неё мы отделим ряды, и начавшиеся и кончившиеся светлой точкой.

Отфильтруем данные по столбцу C  , убрав все нули, и получим ряды, для которых выполнилось условие. Значения из столбцов D  и A  запишем в ответ.

Решение (Python)

f = open(’m7_26_18_04__3u8yv.txt’)

n = int(f.readline())

tr = [list(map(int, i.split())) for i in f]
tr.sort()

new_tr = [[0] * 10_001 for i in range(10_001)] # матрица свободных и занятых мест
for x, y in tr:
    new_tr[x][y] = 1 # отмечаем, что место - занято

max_count = 1
row = 0

for i in range(len(new_tr)):
    # если первое и последнее место в ряду - заняты и при этом в ряду максимальное количество светлых точек
    if new_tr[i][1] == new_tr[i][-1] == 1 and sum(new_tr[i]) > max_count:
        max_count = sum(new_tr[i])
        row = i
print(max_count, row)

Ответ: 13 9298

Ошибка.
Попробуйте повторить позже

Задача 23#87922Максимум баллов за задание: 2

В лесополосе осуществляется посадка деревьев. Причем саженцы высаживают рядами на одинаковом расстоянии.

Через какое-то время осуществляется аэросъемка, в результате которой определяется, какие саженцы прижились. Необходимо определить ряд с максимальным номером, в котором есть ровно 2  неприжившихся саженца, при условии, что справа и слева от них саженцы прижились, а также прижился ровно один саженец между ними. При аэросъемке была совершена ошибка — одно и то же дерево могло быть снято дважды. В ответе запишите сначала наибольший номер ряда, затем наименьший номер из найденных 2  неприжившихся мест в этом ряду.

Входные данные:

В первой строке входного файла находится число N  — количество сфотографированных прижившися саженцев (натуральное число, не превышающее 110000  ). Каждая из следующих N  строк содержит два натуральных числа, не превышающих 10000  : номер ряда и номер саженца.

Выходные данные:

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

Вложения к задаче
Показать ответ и решение

Решение при помощи электронных таблиц:

Сначала перенесем данные из файла в Excel, скопировав и вставив с разделителем пробел, а также удалим первую строчку.

Настраиваемой сортировкой отсортируем в первую очередь по столбцу A  по возрастанию, во вторую - по столбцу B  по возрастанию.

PIC

PIC

Выделим полностью столбцы A  и B  , перейдём в раздел Данные и нажимаем на инструмент Удалить дубликаты, в появившемся окне выбираем Выделить все и нажимаем ОК (это удалит деревья, которые были по ошибке сняты дважды).

В LibreOffice Calc необходимо также выделить оба столбца, применить фильтр и перейти в раздел Фильтр по условию -> Стандартный фильтр.

В условиях фильтра необходимо через И выбрать столбцы A  и B  , установить значение Не пусто и поставить галочку напротив Без повторений. После чего нужно скопировать отфильтрованные значения на новый лист и работать уже там.

PIC

PIC

Чтобы определить, пропущены ли два саженца через один среди прижившихся, в ячейку C1  запишем формулу и растянем её до конца таблицы:

=ЕСЛИ(И(A1=A2;A2=A3;B2-B1=2;B3-B2=2);B1+1;0)

Условие A1 = A2;A2 = A3  обеспечивает попадание трех прижившихся саженцов в один ряд, B2 − B1 = 2;B3 − B2 = 2  - нахождение трёх прижившихся саженцев через одно свободное место друг от друга. Если условия выполнились - записываем в ячейку номер первого неприжившегося саженца из 2-х.

Отфильтруем данные по столбцу C  , убрав все нули, и получим места, для которых выполнилось условие. Значения из столбцов A  и C  последней строчки запишем в ответ.

 

Программное решение

f = open(’26_dif_2__40zqo.txt’)

n = int(f.readline())

tr = [list(map(int, i.split())) for i in f] # считываем файл
tr.sort() # сортируем значения в столбцах по возрастанию

max_row = 0 # максимальный ряд
min_place = 10 ** 10 # минимальной подходящее место в максимальном ряду

for i in range(len(tr) - 2):
    # если ряд трёх рядом стоящих в списке мест совпадает
    if tr[i][0] == tr[i + 1][0] == tr[i + 2][0]:
        # проверка, что между каждыми двумя прижившимися саженцами есть одно свободное место
        if tr[i + 1][1] - tr[i][1] == tr[i + 2][1] - tr[i + 1][1] == 2:
            if max_row == tr[i][0]:
                min_place = min(min_place, tr[i][1] + 1) # вычисляем минимальное место в максимальном ряду
            else:
                min_place = tr[i][1] + 1
            max_row = tr[i][0]

print(max_row, min_place)

Ответ: 3421 5019

Ошибка.
Попробуйте повторить позже

Задача 24#87929Максимум баллов за задание: 2

Организация купила для своих сотрудников все места в нескольких подряд идущих рядах на концертной площадке. Известно, какие места уже распределены между сотрудниками. Найдите ряд с наибольшим номером, в котором есть пять соседних мест, таких что слева и справа от них в том же ряду места уже распределены (заняты). Гарантируется, что есть хотя бы один ряд, удовлетворяющий условию.

Входные данные представлены в файле 26_4.txt следующим образом. В первой строке входного файла находится одно число: N – количество занятых мест (натуральное число, не превышающее 10 000). В следующих N строках находятся пары чисел: ряд и место выкупленного билета, не превышающие 100 000.

В ответе запишите шесть целых чисел через пробел: сначала номер максимального ряда, а затем номера соседних пяти мест в нем в порядке возрастания.

Вложения к задаче
Показать ответ и решение

Решение (Excel/LibreOffice)

Откроем файл в электронной таблице и удалим первую строку. С помощью настраиваемой сортировки отсортируем файл следующим образом: Столбец А по убыванию и столбец В по возрастанию. В ячейку C1  запишем 0 и в ячейку C2  запишем формулу:

=ЕСЛИ(И(A1=A2;B1+6=B2);1;0)

С помощью сочетания клавиш CT RL + F  откроем меню поиска в столбце С найдём первую 1. Как видим, между местами 698 и 704 ряда 1928 есть 5 свободных мест. В ответ указываем номер ряда и номера мест в порядке возрастания.

Решение (Python)

f = open(’26_4.txt’)
n = int(f.readline())
a = [] # список, в котором будут записаны координаты занятых мест
for line in f:
    numbers = list(map(int, line.split()))
    a.append(numbers)
a = sorted(a) # сортируем по возрастанию значения в столбцах
for i in range(len(a)-1):
    # если ряд двух рядом стоящих в списке мест совпадает и между ними есть 5 свободных мест
    if (a[i][0] == a[i+1][0]) and (a[i+1][1] - a[i][1] == 6):
        print(a[i], a[i+1])

Ответ: 1928 699 700 701 702 703

Ошибка.
Попробуйте повторить позже

Задача 25#106916Максимум баллов за задание: 2

При онлайн-покупке билета на концерт известно, какие места в зале уже заняты. Необходимо купить два билета на такие соседние места в одном ряду, чтобы за ними все кресла с такими же номерами были свободны, а ряд находился как можно ближе к сцене. Сцена расположена перед первым рядом. Если в этом ряду таких пар мест несколько, найдите пару с наименьшими номерами мест. Нумерация рядов и мест ведётся с 1. Гарантируется, что хотя бы одна такая пара в зале есть. Определите наименьший номер ряда и наименьший номер места для найденной пары мест.

Входные данные представлены в файле следующим образом. В первой строке входного файла находятся три числа: N  – количество занятых мест в зале (целое положительное число, не превышающее 10000), M  – количество рядов (целое положительное число, не превышающее 100 000) и K  – количество, мест в каждом ряду (целое положительное число, не превышающее 100 000). В следующих N  строках находятся пары натуральных чисел: номер ряда и номер места занятого кресла соответственно (первое число не превышает значения M  , а второе – K  ).

Запишите в ответе два целых числа: искомый номер ряда и наименьший номер места в найденной паре.

Пример входного файла:

7 7 8

1 1

6 6

5 5

6 7

4 4

2 2

3 3

Условию задачи удовлетворяют места 1 и 2 в ряду 3: за креслами 1 и 2 нет занятых мест.

Вложения к задаче
Показать ответ и решение

Решение 1

f = open("26.txt")
n, m, k = map(int, f.readline().split())
row = [[] for i in range(k + 1)]

for i in range(n):
    x, y = map(int, f.readline().split())
    row[y].append(x)

mn_r =  10 ** 10# минимальный ряд
mn_i = 0 # минимальное место
for i in range(1, len(row) - 1):
    # из двух (вертикальных) соседних рядов берем макс место
    # (номер горизонтального ряда  - mn_r), за ним все будут свободны;
    # соответствеенно, чем он меньше, тем ближе к сцене
    if max(row[i + 1] + row[i]) <= mn_r:
        mn_r = max(row[i + 1] + row[i])
        mn_i = i
print(mn_r+1, mn_i)

Решение 2

f = open("26.txt")
n, m, k = map(int, f.readline().split())
a = [[0, m + 1] for i in range(k)]

for i in f:
    x, y = map(int, i.split())
    a[y-1].append(x)

mx = 0 # максимальная длина пустых мест
mn_r = 0 # минимальный ряд
mn_i = 0 # минимальное место
for i in range(k - 1):
    t1 = sorted(a[i], reverse=True)
    t2 = sorted(a[i + 1], reverse=True)
    spot1 = t1[0] - t1[1] - 1 # выясняем сколько пустых мест за текщум
    spot2 = t2[0] - t2[1] - 1 # и за соседним
    if min(spot1, spot2) > mx: # если пустых мест больше чем нашлось раньше
        mx = min(spot1, spot2) # то обновляем максимум
        mn_r = m - mx + 1 # соханяем номер ряда
        mn_i = i # сохраняем номер места
print(mn_r, mn_i + 1)

Ответ: 627 503

Ошибка.
Попробуйте повторить позже

Задача 26#106917Максимум баллов за задание: 2

При онлайн-покупке билета на концерт известно, какие места в зале уже заняты. Необходимо купить два билета на такие соседние места в одном ряду, чтобы перед ними было занято не более двух кресел с такими же номерами, а ряд находился как можно дальше от сцены. Сцена расположена перед первым рядом. Если в этом ряду таких пар мест несколько, найдите пару с наибольшими номерами мест. Нумерация рядов и мест ведётся с 1. Гарантируется, что хотя бы одна такая пара в зале есть. Определите наибольший номер ряда и наибольший номер места для найденной пары мест.

Входные данные представлены в файле следующим образом. В первой строке входного файла находятся три числа: N  – количество занятых мест в зале (целое положительное число, не превышающее 10000), M  – количество рядов (целое положительное число, не превышающее 100 000) и K  – количество, мест в каждом ряду (целое положительное число, не превышающее 100 000). В следующих N  строках находятся пары натуральных чисел: номер ряда и номер места занятого кресла соответственно (первое число не превышает значения M  , а второе – K  ).

Запишите в ответе два целых числа: искомый номер ряда и наибольший номер места в найденной паре.

Пример входного файла:

8 7 4

1 1

4 1

3 2

1 3

2 3

6 3

5 4

7 2

Условию задачи удовлетворяют места 1 и 2 в ряду 6: перед 1 креслом 2 занятых места, а перед 2 местом 1 занятое место.

Вложения к задаче
Показать ответ и решение

Решение 1

f = open("2.txt")
n, m, k = map(int, f.readline().split())
row = [[m+1] for i in range(k)]

for i in range(n):
    x, y = map(int, f.readline().split())
    row[y-1].append(x)

mx_r = 0# максимальный ряд
mx_i = 0 # максимальное место
for i in range(len(row) - 1):
    # из двух (вертикальных) соседних рядов берем макс место
    # (номер горизонтального ряда  - mx_r), перед ним все будут свободны;
    # соответствеенно, чем он больше, тем дальше от сцене
    if max(row[i + 1] + row[i]) >= mx_r:
        x = max(row[i + 1] + row[i])
        while (x in row[i] or x in row[i + 1]
               or len([p for p in row[i] if p < x]) > 2
               or len([p for p in row[i + 1] if p < x]) > 2):
            x -= 1
        if x >= mx_r:
            mx_r = x
            mx_i = i
print(mx_r, mx_i+2)

Решение 2

f = open("26.txt")
n, m, k = map(int, f.readline().split())
a = [[0, m + 1] for i in range(k)]

for i in f:
    x, y = map(int, i.split())
    a[y-1].append(x)

# дублируем массив a удаляя из него до 2х занятых мест минимальных рядов
b = []
for i in range(k):
    b.append(sorted(a[i]))
    if len(b[i]) >= 4:
        b[i].pop(2)
        b[i].pop(1)
    elif len(b[i]) == 3:
        b[i].pop(1)

mx = 0
mx_i = 0 # минимальное место
for i in range(k - 1):
    # print(i, sorted(a[i]))
    t1 = sorted(b[i])
    t2 = sorted(b[i + 1])
    spot1 = t1[1] - t1[0] - 1 # выясняем сколько пустых мест перед текущим
    spot2 = t2[1] - t2[0] - 1 # и перед соседним

    # так как мы ранее удалили часть занятых мест, то нужно проверить, не заняты ли
    # найденные места, если заняты, то спускаемся на ряд ниже, в нем гарантированно
    # выполняются условия задачи
    row = min(spot1, spot2)
    while row in a[i] or row in a[i + 1]:
        row -= 1

    if row >= mx: # если найденный ряд выше чем нашлось ранее
        mx = row # то обновляем максимум
        mx_i = i # и сохраняем номер места
print(mx, mx_i + 2)

Ответ: 80604 9404
Рулетка
Вы можете получить скидку в рулетке!