Выбрать ровно один из пары

Общая идея

Нужно воспользоваться идеей динамического программирования. Будем решать задачу для префикса массива i, и поддерживать dp[i][нечто]. Второе измерение массива dp используем, чтобы удовлетворить ограничения на выбранное множество.

Задача 23 Демо

Условие

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

Разбор

Как в общем работает идея дп? Представим, что мы уже решили задачу для префикса из i элементов. Теперь нужно понять, как изменится ответ, если добавить i+1-ый элемент.

Решим сначала более простую задачу, убрав ограничение "чтобы сумма всех выбранных чисел не делилась на 3". dp[i] - максимальная сумма, если рассмотрен префикс i. Теперь нужно взять один из элементов i+1-ой пары. dp[i + 1] = max(dp[i]+a[i+1].first, dp[i] + a[i+1].second). Вернемся к исходной задаче.

Теперь нужно учитывать ограничение. Для этого дополним наш dp[i]. Заведем dp[i][j]. Второй параметр(второе измерение) должен помогать удовлетворять ограничение. В этой задаче ограничение - сумма по модулю 3. Её и будем поддерживать. j = (сумма набора % 3). Тогда ответ на задачу - max(dp[n][1], dp[n][2]),потому что dp[n][0] - сумма, которая делится на 3. Снова нужно понять, как изменится ответ из текущего состояния dp[i][j], если добавится i+1-ый элемент массива. Мы можем добавить в набор либо первый, либо второй элемент пары. Если добавится, например, первый, то переход такой: dp[i+1][(j+первый_элемент)%3] ← dp[i][j].

Важно правильно проставить начальные значения! Какая сумма у пустого массива? 0 и только 0. Значит у пустого массива не бывает так, что его сумма выбранных элементов по модулю 3 равна 1 или 2. Как раз чтобы пометить состояние как невозможное, мы и присваиваем ему бесконечно малое значение. Тогда, при дальнейшем пересчете dp, обновления через это бесконечно невыгодное состояние не произойдет.

Код


        

        

Похожие задачи: 890,108,912,955

Задача 1380

Условие

На вход программы поступает последовательность из N пар целых положительных чисел. Необходимо выбрать из каждой пары одно число так, чтобы сумма выбранных чисел была максимально возможной и не делилась на 5, при этом сумма невыбранных чисел не делилась на 3.

Разбор

Сделаем похожую динамику. Теперь у нас еще одно условие, которое нужно контролировать. dp[i][j][k]. j - сумма выбранных элементов по модулю 5, k - сумма невыбранных по модулю 3.

Код


        

        

Похожие задачи:

Задача 682

Условие

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

Разбор

Идея та же самая, но теперь нужно выбрать два элемента из трех.

Код


        

        

Похожие задачи: см. следующую задачу

Задача 1208

Условие

Имеется набор данных, состоящий из N троек натуральных чисел. Составьте сумму из N чисел, выбрав из каждой тройки ровно одно число так, чтобы эта сумма не делилась нацело на k = 103 и была максимально возможной. Гарантируется, что искомую сумму получить можно.

N<=1000000

Разбор

Применим известную идею. Тогда размер массива получается 1e6 * 103 ~= 1e8. Это много(может отработать, а может и нет на плохом компе). Нужно соптимизировать. Хотя даже после оптимизации на питоне будет работать несколько минут.

Заметим, что i+1 слой всегда пересчитывается из i-ого. Значит можно не хранить все старые слои. Так и поступим. В коде это решается просто: будем брать каждый индекс %2. И также нужно не забыть очистить i-ый слой, после того как обновили i+1-ый(так как на следующей итерации это будет уже i+2-ой слой).

Код


        

        

Похожие задачи: 1305,1277,1396,1660

Идея-бонус

Предположим вы забыли все и отключилась голова. Есть решение на удачу! Просто найдите максимальную сумму и проверьте, что она удовлетворяет условию. Если да, то это точно правильный ответ, т.к. сумма максимальная. Если нет, то ответ точно неправильный и тогда запишите какое-нибудь число чуть меньше.