Качели в игровом зале
Условие
В игровом зале стоят большие призовые качели: два сиденья и табло, которое показывает разницу веса между левым и правым сиденьем.
После турнира вы выиграли n призов. У каждого приза есть «вес» (целое число). Призы нужно разложить по двум сиденьям (каждый приз — ровно на одно сиденье), чтобы разница суммарных весов была как можно меньше.
Чтобы ведущий не спорил с вами, договоримся о каноническом ответе:
- мы выводим индексы призов (нумерация с 1), которые кладём на левое сиденье;
- среди всех раскладок с минимальной возможной разницей выбираем ту, где суммарный вес левого сиденья не превосходит суммарный вес правого;
- если и таких несколько, выбираем раскладку с лексикографически минимальным списком индексов левого сиденья (индексы внутри списка идут по возрастанию).
Формат ввода
Первая строка: целое число n. Вторая строка: n целых чисел a1, a2, ..., an — веса призов.
Формат вывода
В первой строке выведите одно целое число — минимальную возможную разницу между суммами весов на двух сиденьях. Во второй строке выведите число k — сколько призов на левом сиденье, а затем k индексов этих призов в возрастающем порядке (канонический выбор по правилам выше).
Ограничения
- 1 ≤ n ≤ 20
- 1 ≤ ai ≤ 1 000 000
Пример
Ввод:
4
10 7 6 5
Вывод:
2
2 2 3
В этом примере на левое сиденье кладём призы с весами 7 и 6 (индексы 2 и 3), на правое — 10 и 5. Разница равна 2, и это минимум.
Как решать — идея подхода
Приём: Перебор подмножеств битмаской
Ключевое наблюдение: раскладка однозначно задаётся выбором множества призов для левого сиденья. Тогда правая сумма — это total - left, а разница равна abs(total - 2*left). По правилу каноничности нам нужны только варианты с left <= right, то есть left <= total//2 — это сразу режет половину перебора.
Почему работает перебор: n <= 20, значит подмножеств 2^n всего до 1 048 576 — это реально посчитать в лоб.
План:
- Считай
total = sum(a)иhalf = total // 2. - Иди по всем
maskот 0 до(1<<n)-1. - Для каждого
maskпосчитайleft(сумму весов тех i, где бит 1). - Если
left > half, пропусти (иначе нарушимleft <= right). - Посчитай разницу:
diff = total - 2*left(она неотрицательна из-за фильтра). - Обновляй лучший ответ:
- берём меньший
diff; - при равном
diffвыбираем лексикографически минимальный список индексов слева (индексы по возрастанию). - В конце выведи
best_diffи сам список индексов.
Сложность: O(n * 2^n) по времени и O(1) доп. памяти (кроме хранения ответа).
Частая ошибка: сравнивать лексикографически «маски» или строки, а не списки индексов. Правильнее сравнивать именно последовательности индексов слева (например, [2,3] < [2,4], а [2,3] < [2,3,5]).
Разберись руками
Есть 4 приза с весами 10, 7, 6, 5. Каждый приз кладём либо на левое сиденье, либо на правое. Нужно выбрать, что кладём налево, чтобы разница весов получилась как можно меньше, и при этом слева было не тяжелее, чем справа.
- Сначала посчитай общий вес всех призов: 10 + 7 + 6 + 5 = ?
- Переберём ВСЕ варианты, какие индексы могут лежать слева (1..4). Отметь те варианты, где слева НЕ тяжелее, чем справа. (То есть сумма слева ≤ 14, потому что общий вес 28.)
- Теперь среди ВСЕХ вариантов выбери те, где разница между правым и левым минимальна, но всё ещё слева ≤ справа. (Для каждого кандидата: разница = (вес справа) − (вес слева).)
- Посчитай минимальную разницу для выбранного варианта слева [2,3]. Слева 7+6, справа 10+5. Разница = ?
Идея: Сначала считаем общий вес. Потом перебираем все варианты, какие призы положить слева, и оставляем только те, где слева не тяжелее. Для каждого такого варианта считаем разницу между сиденьями и выбираем вариант с самой маленькой разницей; если лучших несколько — берём тот, у которого список индексов слева «самый ранний» при сравнении по порядку.
Решить задачу с автопроверкой на Python →
Куда дальше
- Школьный этап ВсОШ по информатике — как устроен первый этап и план подготовки за четыре недели
- Родителям: подготовка бесплатно — сколько стоит репетитор, что даёт бесплатный маршрут и как понять, что ребёнок занимается
- БВИ и льготы при поступлении — какой диплом что даёт и сколько лет он действует