Олімпійський багаж#3613

Олімпійський багаж (Розбір)

Об'явимо масив , в якому прийме значення , якщо за допомогою наявних предметів можна набрати сумарну вагу . Спочатку покладемо mask[0] = 1.

Припустимо, що масив вже коректно заповнений для деякого набору предметів. Розглянемо наступний предмет ваги . Тоді необхідно встановити mask[i] = 1 для всіх значень i~(w \le i \le m), для яких виконується умова mask[i - w] = 1.

Приклад

Розглянемо, як змінюються значення комірок масиву під час обробки предметів. Ліворуч вказані ваги предметів.

Максимальна вага досягається для підмножини \{2, 1, 1\}.

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

Масив зберігаємо у вигляді бітової маски, інакше рішення не вкладеться в обмеження по пам'яті.

#define MAX 30000010
bitset<MAX> mask;

Читаємо вхідні дані. Встановлюємо mask[0] = 1.

scanf("%d %d",&m,&n);
mask.set(0);

Розглянемо обробку чергового предмета ваги . Проходимо по масиву справа наліво і встановлюємо mask[j] = 1 для всіх значень j~(w \le j \le m), для яких mask[j - w] = 1.

for (i = 0; i < n; i++)
{
  scanf("%d",&w);
  for (j = m; j >= w; j--)
   if (mask[j - w] == 1) mask.set(j);
}

Після обробки всіх предметів знаходимо найбільшу вагу, що не перевищує , яку можна покласти в багаж, і виводимо її.

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