Leetcode 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.

题目的意思是给出一串非负数的数组,求其中的一个子集,这个子集在原数组中两两都不相邻而且子集的和最大。

假设数组为num[n], 我们在对第i个数进行处理的时候,我们可以选num[i]或者不选num[i],这样就有两种情况:

1、选择num[i],那么num[i-1]一定不能选

2、不选择num[i],那么num[i-1]可以选也可以不选,这个是由num[i-2]决定的

我们设两个数组choose[n],nchoose[n],其中choose中第i个元素的值为从num[0]~num[i]中,子集选取了num[i]中的值的最大值;nchoose则相反为第i个元素的值为从num[0]~num[i]中,子集没有选取了num[i]中的值的最大值,则可知:
choose[i] = nchoose[i-1] + num[i]                                

(选取i必须得i-1没有被选取,则nchoose[i-1]刚刚好保存了没有选取i-1的最大值)

nchoose[i] = max(choose[i-1], nchoose[i-1])               

(不选取i的话,i-1可能被选了,也可能不被选,我们选取其最大值)

结果选了最后一个元素的情况:

如num数组为: 1          5          4          3          8          7          4          6          8 

则choose:      1          5          5          8          13        15       17         21       25

nchoose数组 :   0          1          5          5          8          13       15         17       21

结果没选最后一个元素的情况:

如num数组为: 1          5          4          3          8          7          4          6          1 

则choose:      1          5          5          8          13        15       17         21        18

nchoose数组 :   0          1          5          5          8          13       15        17        21

所以要返回两个数组最后一个值之中的最大值

所以代码(C++)为:

class Solution {
public:
    int rob(vector<int> &num) {
        if (num.empty()) return 0;
        if (num.size()==1) return num[0];
        if (num.size()==2) return num[0]>num[1]?num[0]:num[1];
        vector <int> choose, nchoose;
        choose.push_back(num[0]);
        choose.push_back(num[1]);
        nchoose.push_back(0);
        nchoose.push_back(num[0]);
        for (size_t i=2; i<num.size(); ++i)
        {
        	choose.push_back(nchoose[i-1] + num[i]);
        	nchoose.push_back(choose[i-1] > nchoose[i-1] ? choose[i-1] : nchoose[i-1]);
		}
		return (choose.back()>nchoose.back()?choose.back():nchoose.back());
    }
};

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值