Leetcode 198 House Robber 搶劫最大金額

原題地址

https://leetcode.com/problems/house-robber/

題目描述

You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security system connected and it will automatically contact the police if two adjacent houses were broken into on the same night.
你是一個專業的強盜,計劃去搶一條街上的房子。每個房子裏都有一定量的錢,唯一限制你搶掉所有房子裏的錢的是:相鄰的房子的安保系統是連接在一起的,如果相鄰的兩個房子在同一晚上都被盜的話就會自動報警。

Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonight without alerting the police.
給出一系列非負的整數代表每個房子內的金錢數量,計算你今晚不觸發報警條件的情況下可以搶到的最多的錢。

Tags Dynamic Programming

解題思路

對於求解這個問題,關鍵問題是對於某間房子,我們搶還是不搶。假設我們用rob[i]表示搶劫第i間房子的情況下在之後的所有房子裏可以得到的最大金額,用notRob[i]表示不搶劫第i間房子的情況下在之後的所有房子裏可以得到的最大金額。在求解rob[i]時,搶劫第i間房子,很明顯不能繼續搶劫它的下一間房子,因此rob[i]需要根據notRob[i+1]來計算,對於notRob[i],我們不搶第i間房子時,第i+1間房子既可以搶也可以不搶,我們根據rob[i+1]和notRob[i+1]之間的較大者來計算notRob[i]。

rob[i] : 在搶劫第i間房子的情況下,可以從其之後的所有房子裏(nums[i]~nums[n])獲得的金錢。

notRob[i] : 在不搶劫第i間房子的情況下,可以從其之後的所有房子裏(nums[i]~nums[n])獲得的金錢。

有如下方程來計算:

rob[i]=num[i]+notRob[i+1]
如果搶劫了第i間,一定不能搶劫後面相鄰的房子。

notRob[i]=bigger(rob[i+1],notRob[i+1])
如果沒有搶劫第i間,可以搶或者不搶後面相鄰的房子。

算法

  1. 初始化最後一天的rob[n]=num[n]和notRob[n]=0
  2. 從後往前處理,rob[i] = num[i] + notRob[i + 1],notRob[i] = bigger(rob[i + 1], notRob[i + 1])
  3. 返回bigger(rob[0], notRob[0]);

代碼

/**
 * 計算可能搶劫的最大數額
 * @param nums 每個房子中的金額
 * @param numsSize 房子數量
 * @return 搶劫的最大數額
 */
int rob(int* nums, int numsSize) {
    int bigger(int, int);

    if (numsSize == 0) return 0;

    // 搶劫某間房子時,可以從後面的所有房子裏搶劫的最大金額
    int *maxWhenRob = (int *)malloc(sizeof(int) * numsSize);
    // 不搶劫某間房子時,可以從後面的所有房子裏搶劫的最大金額
    int *maxWhenNotRob = (int *)malloc(sizeof(int) * numsSize);

    int index = numsSize - 1;
    /* 初始化最後一天的數據 */
    *(maxWhenRob + index) = *(nums + index);
    *(maxWhenNotRob + index) = 0;
    /* 循環處理之前的房子 */
    for (--index; index > -1; --index) {
        // 搶劫某間房子一定不能搶後面的相鄰的房子
        *(maxWhenRob + index) = *(nums + index) + *(maxWhenNotRob + index + 1);
        // 不搶某間房子,其後面的房子可以搶也可以不搶,選其中的較大者
        *(maxWhenNotRob + index) = bigger(
                *(maxWhenRob + index + 1), *(maxWhenNotRob + index + 1));
    }

    int max = bigger(*maxWhenRob, *maxWhenNotRob);
    free(maxWhenRob);
    free(maxWhenNotRob);
    return max;
}

/** 返回兩者中的較大者 */
int bigger(int a, int b) { return a > b ? a : b; }

完整代碼 https://github.com/Orange1991/leetcode/blob/master/198/cpp/main.c

測試數據

[4,3,5,6,1,2,0,4,2,5] : 21

2015/8/5

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章