Эту проблему можно решить с помощью динамического программирования.
Допустим, у нас есть массив целых чисел:
i[1], i[2], i[3], ..., i[n], i[n+1], i[n+2]
Мы разбиваем массив на две части: первая часть содержит первые n целых чисел, а вторая часть - последние два целых числа:
{i[1], i[2], i[3], ..., i[n]}, {i[n+1], i[n+2]}
Обозначим M_SUM(n)
как максимальную сумму первых n целых чисел по вашему требованию.
Будет два случая:
- если
i[n]
не учитывается в M_SUM(n)
, то M_SUM(n+2) = M_SUM(n) + MAX(i[n+1], i[n+2])
- если
i[n]
засчитано в M_SUM(n)
, то M_SUM(n+2) = M_SUM(n) + i[n+2]
тогда M_SUM(n+2)
, значение, которое мы ищем, будет большим значением из вышеупомянутых двух.
Тогда у нас может быть очень наивный псевдокод, как показано ниже:
function M_SUM(n)
return MAX(M_SUM(n, true), M_SUM(n, false))
function M_SUM(n, flag)
if n == 0 then return 0
else if n == 1
return flag ? i[0] : 0
} else {
if flag then
return MAX(
M_SUM(n-2, true) + i[n-1],
M_SUM(n-2, false) + MAX(i[n-1],i[n-2]))
else
return MAX(M_SUM(n-2, false) + i[n-2], M_SUM(n-2, true))
}
«флаг» означает «разрешить использование последнего целого числа»
Этот алгоритм имеет экспоненциальную сложность по времени.
Методы динамического программирования могут использоваться для устранения ненужного пересчета M_SUM.
Сохранение каждого M_SUM(n, flag)
в матрицу n * 2. В части рекурсии, если такого значения нет в матрице, вычислите его. В противном случае просто получите значение из матрицы. Это уменьшит сложность времени до линейной.
Алгоритм будет иметь O (n) временную сложность и O (n) пространственную сложность.