Фруктове свято#11161

Фруктове свято (Розбір)

Є рюкзак місткістю . Доступні дві речі з вартостями і . Кожну з них можна класти в рюкзак довільну кількість разів. Розв'язуємо задачу про рюкзак для двох речей.

Нехай dp[i] = 1, якщо Бессі може отримати ситість, що дорівнює . Тепер Бессі п'є воду. А саме, для кожного значення , для якого dp[i] = 1, встановимо dp[i / 2] = 1.

Тепер знову розв'язуємо задачу про рюкзак для двох речей. Знаходимо ситості, яких зможе досягти Бессі після того, як випила воду.

Приклад

Розглянемо наведений приклад. Розв'язуємо задачу рюкзака для апельсинів і лимонів.

Бессі п'є воду.

Знову розв'язуємо задачу рюкзака для апельсинів і лимонів.

Максимальна ситість Бессі дорівнює .

Реалізація алгоритму

Оголосимо масив , у якому dp[i] = 1, якщо Бессі може отримати ситість, що дорівнює .

#define MAX 5000001
int dp[MAX];

Читаємо вхідні дані.

scanf("%d %d %d", \&t, \&a, \&b);

Ініціалізуємо рюкзак: ситість можна досягти, якщо нічого не їсти.

dp[0] = 1;

У рюкзак кладемо апельсини.

for (i = a; i \<= t; i++)
  if (dp[i - a] == 1) dp[i] = 1;

У рюкзак кладемо лимони.

for (i = b; i \<= t; i++)
  if (dp[i - b] == 1) dp[i] = 1;

Бессі п'є воду. Якщо ситість досягнута, то ситість також може бути досягнута.

for (i = 1; i \<= t; i++)
  if (dp[i] == 1) dp[i / 2] = 1;

Знову розв'язуємо задачу рюкзака для апельсинів і лимонів.

for (i = a; i \<= t; i++)
  if (dp[i - a] == 1) dp[i] = 1;
for (i = b; i \<= t; i++)
  if (dp[i - b] == 1) dp[i] = 1;

Знаходимо і виводимо максимальну ситість, якої може досягти Бессі.

for (i = t; i \> 0; i--)
  if (dp[i] == 1) break;
printf("%d\n", i);

Python реалізація

Читаємо вхідні дані.

t, a, b = map(int, input().split())

Оголосимо масив , у якому dp[i] = 1, якщо Бессі може отримати ситість, що дорівнює .

dp = [0] * (t + 1)

Ініціалізуємо рюкзак: ситість можна досягти, якщо нічого не їсти.

dp[0] = 1

У рюкзак кладемо апельсини.

for i in range(a, t + 1):
  if dp[i - a] == 1: dp[i] = 1

У рюкзак кладемо лимони.

for i in range(b, t + 1):
  if dp[i - b] == 1:  dp[i] = 1

Бессі п'є воду. Якщо ситість досягнута, то ситість також може бути досягнута.

for i in range(1, t + 1):
  if dp[i] == 1: dp[i // 2] = 1

Знову розв'язуємо задачу рюкзака для апельсинів і лимонів.

for i in range(a, t + 1):
  if dp[i - a] == 1: dp[i] = 1
for i in range(b, t + 1):
  if dp[i - b] == 1: dp[i] = 1

Знаходимо і виводимо максимальну ситість, якої може досягти Бессі.

for i in range(t, 0, -1):
  if dp[i] == 1: break
print(i)