Как указывает siralexsir88 в комментариях, недостаточно только проверять решения для ограбления четных / нечетных домов, поскольку может случиться так, что лучшая стратегия состоит в том, чтобы пропустить более одного домав ряд.
Данный пример иллюстрирует этот факт: предположим, у вас есть [1, 3, 5, 2, 1, 7], здесь индексы 3 и 4 должны быть пропущены, чтобы выбрать последние 7.
Предлагаемое решение
Эта проблема является типичным примером динамического программирования и может быть решена путем рекурсивного построения решения.
Для каждого дома есть дваварианты: вы либо ограбить его, наш вы не. Давайте отследим лучшее решение для обоих случаев и для каждого дома: назовем R[i]
максимальная прибыль до i-го дома , если мы ограбим i-й дом . Давайте определим NR[i]
таким же образом, чтобы не грабил i-й шланг .
Например, предположим, что у нас есть [1, 3]. В этом случае:
R[0] = 1
NR[0] = 0
R[1] = 3
Наилучшая прибыль при ограблении дома № 1 составляет 3 NR[1] = 1
Наилучшая прибыль, не грабя дом № 1, равна 1
Давайте также назовем P[i]
прибыль, которая дает нам ограбление i-го дома. Мы можем построить наше решение рекурсивно в терминах R
и NR
следующим образом:
1) R[i] = NR[i-1] + P[i]
2) NR[i] = max(NR[i-1], R[i-1])
3) R[0] = P[0]
4) NR[0] = 0
Давайте разберем его.
Рекурсивное отношение 1) говорит, что если мы ограбимВ этом доме мы не должны были грабить предыдущий дом и, следовательно, взять не грабить лучший результат за предыдущий дом.
Рекурсивное отношение 2) говорит, что если мы не грабимВ этом случае наша оценка является лучшей из тех, которые грабят, а не грабят предыдущий. Это имеет смысл, потому что мы ничего не добавляем к нашей общей прибыли, мы просто сохраняем лучшую прибыль на данный момент.
3) и 4) - это только начальные условия для первого дома, которые должны иметь смысл доэта точка.
Вот фрагмент псевдопифон, который вычисляет наилучшую прибыль:
P = [1, 3, 5, 2, 1, 7] # The houses
R = [0] * len(P)
NR = [0] * len(P)
R[0] = P[0]
# We skip index 0
for i in range(1, len(P)):
R[i] = NR[i-1] + P[i]
NR[i] = max(NR[i-1], R[i-1])
# The solution is the best between NR and R for the last house
print max(NR[-1], R[-1])
Решение подразумевает отслеживание двух массивов (R[i]
и NR[i]
)во время обхода домов, а затем сравнить результаты в конце. Если вы просто хотите получить максимальную прибыль, вы можете сохранить результаты R
и NR
для предыдущего дома и отказаться от них по мере продвижения. Однако, если вы хотите точно знать, какая последовательность домов приводит к наилучшему результату, вам необходимо отслеживать весь массив, и, как только вы закончите, вернитесь назад и восстановите решение.