迭代法求解抢劫犯问题
朋友圈的一个编程题目。如下是本人的分析和答案。
抢劫犯问题
问题描述:
假如你是一个职业抢劫犯,你打算洗劫一个街道。每一个房子里有一定数量的钱。限制你的唯一条件是,
相邻的房子的安保系统是相连的。如果你抢劫相邻的房子,那么安保系统就会惊动警察。
给定一个非负整数的列表代表每个房子当中的钱,计算在不惊动警察的情况下你可以抢劫到的最多的钱。
输入样例:第一行为数列
4
0 2 3 4
5
1 3 0 3 10
输出样例:
6
13
问题分析:
递归思路:
针对n个数据,记最大累加和为F(n)(n>=3)。
对于F(n-1)和F(n-2),如果:
- F(n-1) == F(n-2),则a(n-1)未计入F(n-1),此时F(n) = F(n-2) + an
- F(n-1) > F(n-2),则a(n-1)计入F(n-1),此时F(n) = max(F(n-2) + an, F(n-1))
- F(1) = a1
- F(2) = max(a1, a2)
这个递归算法,时间复杂度和空间复杂度都是O(n^2),我们必须优化一下,将递归展开为迭代形式。
优化后的算法,时间复杂度为O(n),空间复杂度为O(1)。
解答:
#include <iostream>
using namespace std;
unsigned int fun(unsigned int * const a, int n)
{
unsigned int f1 = 0, f2 = 0, fn = 0;
if (n == 1)
return a[0];
else if (n == 2)
return a[1] > a[0] ? a[1] : a[0];
else if (n >= 3) {
f1 = a[0];
fn = f2 = a[1] > a[0] ? a[1] : a[0];
for (int i = 2; i < n; i++) {
f1 = f2;
f2 = fn;
if (f2 == f1)
fn = f1 + a[i];
else if (f2 > f1)
fn = f1 + a[i] > f2 ? f1 + a[i] : f2;
}
return fn;
}
return 0;
}
int main()
{
unsigned int *a;
int n;
while (cin >> n)
{
a = new unsigned int[n];
for (int i = 0; i < n; i++)
{
cin >> a[i];
}
cout << fun(a, n) << endl;
delete[] a;
}
return 0;
}

浙公网安备 33010602011771号