Киоск: сдача без сдачи

тема: Перебор подмножеств (bitmask) · уровень: базовый

Условие

Ты зашёл в школьный киоск. У тебя в кармане лежат несколько купюр/монет с фиксированными номиналами. Продавец вредничает и просит заплатить ровно без сдачи. Каждую купюру можно использовать не больше одного раза.

Определи, получится ли набрать ровно нужную сумму.

Формат ввода

В первой строке записаны два целых числа n и S — количество купюр и нужная сумма. Во второй строке записаны n целых чисел a1, a2, ..., an — номиналы купюр.

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

Выведи YES, если можно выбрать некоторые купюры так, чтобы их сумма была ровно S. Иначе выведи NO.

Ограничения

Пример

Ввод:

5 11
1 2 5 9 10

Вывод:

YES

(например, 1 + 10 = 11)

Как решать — идея подхода

Приём: Перебор подмножеств битмаской

Ключевое наблюдение: купюр всего до 18, значит количество всех вариантов выбора «взять/не взять» равно 2^n — это всего 262144. Такой перебор легко укладывается по времени.

Приём: битмаска (binary mask) — число от 0 до 2^n - 1, где i-й бит показывает, берём ли купюру a[i]. Почему работает: каждый набор купюр однозначно соответствует своей маске, и мы гарантированно проверяем все возможные подмножества.

План решения:

Мини-сниппет проверки бита:

Сложность: O(n * 2^n), при n=18 это около 4–5 миллионов операций.

Частая грабля: забыть, что сумма S может быть 0. Тогда подходит пустое множество (маска 0), и ответ должен быть YES.

Разберись руками

Нужно заплатить ровно 11, а купюры такие: 1, 2, 5, 9, 10. Каждую купюру можно взять или не взять, но нельзя взять дважды. Проверим на руках, как искать подходящий набор.

Идея: Считай, что у каждой купюры есть два решения: взять или не взять. Перебери все такие варианты наборов, для каждого быстро посчитай сумму, и как только встретится ровно нужная сумма — отвечай YES; если перебрал всё и не нашёл — NO.

Решить задачу с автопроверкой на Python →

Куда дальше