leecode 解题总结:213. House Robber II

本文探讨了在房屋排列成环形的情况下,如何通过动态规划算法确定最大抢劫金额而不触发警报的问题。针对这一问题,文章详细介绍了动态规划方程,并提供了一种高效的解决方案。
#include <iostream>
#include <stdio.h>
#include <vector>
#include <string>
using namespace std;
/*
问题:
Note: This is an extension of House Robber.

After robbing those houses on that street, the thief has found himself a new place for his thievery so that he will not get too much attention. This time, all houses at this place are arranged in a circle. That means the first house is the neighbor of the last one. Meanwhile, the security system for these houses remain the same as for those in the previous street.

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.

分析:此题修改题目为环,确实可以增加获取的财富,但要明确如果已经获取过的人家,就需要被设置删除标记位,
删除后的还是否默认相邻? 因为默认相邻,如果遍历一遍返回回来发现比如最后一户和第一户都被遍历了,
说明不符合条件,这个看上去和环相关的应该是一个回溯问题
举例:例如下图5户人家,顺时针开始,如果初始从4开始,下一户就是1
		1
	2		3
	  4	  2
也就是说选定第一个结点,最后一个节点不能访问。我们遍历所有节点作为第一个节点,求出倒数第二个结点的最大值即可
设dp[i]表示A[0...i]的最大财富
dp[i]=max{dp[i-1] , dp[j] + A[i]},j属于[0, i-2]
dp[0]=A[0],dp[1]=A[1],
所求目标dp[n-2],n为A的长度

注意边界:只有1户,可以访问;只有2户,因为彼此相连,选择其中大的
对于选择任意点作为起始点,当遍历到某个点为n-1的时候,设置下一次遍历的时候i=0
i = beg - 2,处理完后,结束遍历

输入:
5(结点个数)
4 2 1 3 2
4
2 1 1 2
1
1
2 
1 2
3
0 0 0
输出:
7
3
1
2
0

关键:
1 参考:https://leetcode.com/problems/house-robber-ii/?tab=Solutions
动态规划方程: dp[i]=max{dp[i-1] , dp[i-2] + A[i]}
可以用pre代替dp[i-1],用cur代替dp[i],然后更新pre=cur,temp=max(pre,cur),cur=temp
另外有了环之后:等于遍历0到n-2,或者1到n-1,为什么2到n-1,再到0不需要考虑,3到n-1到1不需要考虑
因为只有第0个房间与最后第n-1个房间相连,只存在遍历第0个房间与否的问题
2 报错:Input:[0,0,0]
Output:-2147483648
Expected:0
原因:初始设定的最大值为0。而不是INT_MIN。3个元素就应该返回三个中最大的

*/

class Solution {
public:
	int robHelper(vector<int>& nums , int begin , int end)
	{
		int pLast = 0;
		int ppLast = 0;
		for(int i = begin ; i <= end; i++)
		{
			int temp = pLast;
			pLast = max(pLast , ppLast + nums.at(i));
			ppLast = temp;
		}
		return pLast;//最后一次求的结果,参见pLast = max(pLast , ppLast + nums.at(i));
	}

    int rob(vector<int>& nums) {
		if(nums.empty() )
		{
			return 0;
		}
		if(1 == nums.size())
		{
			return nums.at(0);
		}
		if(2 == nums.size())
		{
			return max(nums.at(0) , nums.at(1));
		}
		int n = nums.size();
		return max( robHelper(nums , 0 , n-2) , robHelper(nums , 1 , n - 1) );
	}
};

void process()
{
	 vector<int> nums;
	 int value;
	 int num;
	 Solution solution;
	 while(cin >> num )
	 {
		 nums.clear();
		 for(int i = 0 ; i < num ; i++)
		 {
			 cin >> value;
			 nums.push_back(value);
		 }
		 int answer = solution.rob(nums);
		 cout << answer << endl;
	 }
}

int main(int argc , char* argv[])
{
	process();
	getchar();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值