Збір призів#1619

Збір призів (Розбір)

Перенумеруємо коробки, починаючи з першої (-а коробка містить a_i очок). Нехай позначає максимальну суму очок, яку можна отримати, розглядаючи коробки з по -у включно.

Тоді:

При обчисленні розглянемо два випадки:

Таким чином

f(i) = max(f(i - 2) + a_i, f(i - 1))

Запам'ятаємо значення в масиві . Відповіддю задачі буде значення f(n) = res[n].

Приклад

Розглянемо обчислення f(3)

Якщо третю коробку не відкривати, то ми просто отримаємо найкращий результат для перших двох коробок: f(2) = 6.

Якщо третю коробку відкрити, то другу відкрити вже не можна (вони сусідні). Отже, можна взяти оптимальний результат для першої коробки і додати очки з третьої:

f(1) + a_3 = 6 + 2 = 8

Обираємо максимум з двох варіантів:

f(3) = max(f(2), f(1) + a_3) = max(6, 8) = 8

Розглянемо обчислення f(4)

Якщо четверту коробку не відкривати, то результат дорівнює f(3) = 8.

Якщо четверту коробку відкрити, то третю відкрити не можна. Отже, беремо найкращий результат для перших двох коробок і додаємо очки з четвертої:

f(2) + a_4 = 6 + 10 = 16

Обираємо максимум з двох варіантів:

f(4) = max(f(3), f(2) + a_4) = max(8, 16) = 16

Вправа

Обчисліть значення для наступних вхідних даних:

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

Оголосимо вхідний масив та результуючий .

#define MAX 1000001
long long a[MAX], res[MAX];

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

scanf("%d",&n);
for (i = 1; i <= n; i++)
  scanf("%lld",&a[i]);

Обчислюємо відповідь для однієї res_1 та двох res_2 коробок.

res[1] = a[1];
if (n > 1) res[2] = max(a[1],a[2]);

Обчислюємо відповіді для решти коробок.

for (i = 3; i <= n; i++)
  res[i] = max(res[i - 2] + a[i], res[i - 1]);

Виводимо відповідь.

printf("%lld\n",res[n]);

Java реалізація

import java.util.*; 

class Main 
{
  static long a[] = new long[1000001];
  static long res[] = new long[1000001];

  public static void main(String[] args) 
  {
    Scanner con = new Scanner(System.in);
    int n = con.nextInt();
    for (int i = 1; i <= n; i++)
      a[i] = con.nextInt();
    
    res[1] = a[1];
    if (n > 1) res[2] = Math.max(a[1],a[2]);

    for (int i = 3; i <= n; i++)
      res[i] = Math.max(res[i - 2] + a[i], res[i - 1]);

    System.out.println(res[n]);
    con.close();
  }
}

Python реалізація

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

n = int(input())
lst = list(map(int,input().split()))

Ініціалізуємо список .

dp = [0] * len(lst)

Обчислюємо відповідь для однієї dp_0 та двох dp_1 коробок.

dp[0] = lst[0]
if (n > 1): dp[1] = max(lst[0], lst[1])

Обчислюємо відповіді для решти коробок.

for i in range(2, len(lst)):
  dp[i] = max(dp[i-1], dp[i-2] + lst[i])

Виводимо відповідь.

print(dp[-1])