В видеоигре n призовых коробок расположены в ряд. В
каждой коробке находится некоторое количество очков. По правилам игры нельзя
выбирать соседние коробки – если будут открыты две соседние коробки, сработает
система тревоги, и вы потеряете все призы.
Зная количество
очков в каждой коробке, определите максимальное число очков, которое можно
собрать, не вызвав тревогу.
Вход. Первая строка содержит количество коробок n (1 ≤ n
≤ 106). Вторая строка содержит n целых неотрицательных чисел a1,
a2, ..., an, где ai – количество очков, которое можно получить
из i-й коробки.
Выход. Выведите максимальное
количество очков, которое можно собрать без срабатывания тревоги.
![]()
|
Пример
входа |
Пример
выхода |
|
5 6 1 2 10 4 |
16 |
динамическое
программирование
Анализ алгоритма
Перенумеруем коробки,
начиная с первой (i-ая коробка
содержит ai очков). Пусть
f(i) обозначает максимальную
сумму очков, которую
можно получить, рассматривая коробки с 1 по i-ую
включительно.
Тогда:
·
f(1) = a1,
·
f(2) = max(a1,
a2)
При вычислении
f(i) рассмотрим два случая:
·
если выбирается i-я
коробка, то соседняя (i – 1)-ая коробка недоступна. В этом
случае максимальная сумма очков будет равна f(i – 2) + ai.

·
если i-я коробка не выбирается,
то максимальная сумма очков равна f(i
– 1).

Таким образом
f(i) = max(f(i – 2) + ai,
f(i – 1))
Запомним
значения f(i) в массиве res. Ответом задачи будет значение f(n) = res[n].
Пример


Рассмотрим
вычисление f(3)
Если третью коробку не
открывать, то мы просто получим лучший результат для первых двух коробок: f(2) = 6.
Если третью коробку
открыть, то вторую открыть уже нельзя (они соседние). Значит можно взять
оптимальный результат для первой коробки и прибавить очки из третьей:
f(1) + a3
= 6
+ 2 = 8
Выбираем максимум из двух
вариантов:
f(3) = max(f(2), f(1) + a3)
= max(6, 8) = 8
Рассмотрим
вычисление f(4)
Если четвёртую коробку не
открывать, то результат равен f(3) = 8.
Если четвёртую коробку
открыть, то третью открывать нельзя. Значит берём лучший результат для первых
двух коробок и прибавляем очки из четвёртой:
f(2) + a4
= 6
+ 10 = 16
Выбираем максимум из двух
вариантов:
f(4) = max(f(3), f(2) + a4)
= max(8, 16) = 16
Упражнение
Вычислите
значения f(i) для следующих входных
данных:

Реализация алгоритма
Объявим входной
массив а и результирующий res.
#define MAX 1000001
long long
a[MAX], res[MAX];
Читаем входные
данные.
scanf("%d",&n);
for (i = 1; i <= n; i++)
scanf("%lld",&a[i]);
Вычисляем ответ для одной res1 и двух res2 коробок.
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)
Вычисляем ответ
для одной dp0 и двух dp1 коробок.
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])