迭代法求解抢劫犯问题

朋友圈的一个编程题目。如下是本人的分析和答案。

抢劫犯问题

问题描述:

假如你是一个职业抢劫犯,你打算洗劫一个街道。每一个房子里有一定数量的钱。限制你的唯一条件是,
相邻的房子的安保系统是相连的。如果你抢劫相邻的房子,那么安保系统就会惊动警察。

给定一个非负整数的列表代表每个房子当中的钱,计算在不惊动警察的情况下你可以抢劫到的最多的钱。

输入样例:第一行为数列
4 
0 2 3 4 
5 
1 3 0 3 10 
输出样例:
6 
13

问题分析:

递归思路:

针对n个数据,记最大累加和为F(n)(n>=3)。
对于F(n-1)和F(n-2),如果:

  1. F(n-1) == F(n-2),则a(n-1)未计入F(n-1),此时F(n) = F(n-2) + an
  2. F(n-1) > F(n-2),则a(n-1)计入F(n-1),此时F(n) = max(F(n-2) + an, F(n-1))
  3. F(1) = a1
  4. 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;
}

  

 

posted @ 2018-06-28 00:51  鸿远科技  阅读(11)  评论(0)    收藏  举报  来源