1. 程式人生 > >leetcode---213. 打家劫舍 II

leetcode---213. 打家劫舍 II

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

你是一個專業的小偷,計劃偷竊沿街的房屋,每間房內都藏有一定的現金。這個地方所有的房屋都圍成一圈,這意味著第一個房屋和最後一個房屋是緊挨著的。同時,相鄰的房屋裝有相互連通的防盜系統,如果兩間相鄰的房屋在同一晚上被小偷闖入,系統會自動報警

給定一個代表每個房屋存放金額的非負整數陣列,計算你在不觸動警報裝置的情況下,能夠偷竊到的最高金額。

輸入: [2,3,2]輸出: 3解釋: 你不能先偷竊 1 號房屋(金額 = 2),然後偷竊 3 號房屋(金額 = 2), 因為他們是相鄰的。

示例 2:輸入:

[1,2,3,1] 輸出: 4 解釋: 你可以先偷竊 1 號房屋(金額 = 1),然後偷竊 3 號房屋(金額 = 3)。   偷竊到的最高金額 = 1 + 3 = 4 。

思路:dp很容易找到遞推公式。

但是形成環有點複雜,明白可以分為兩種情況,第一種(型別1)第一個元素不用,就可以訪問最後一個元素。第二種(型別2)是第一個使用,那麼就只能到倒數第二個。我考慮複雜了,一直思考存在一種情況,假設是第一個使用(型別2),但是到推到了倒數第二的時候可能的選擇是沒有搶第一個,這個是不是可以到再考慮最後一個呢。這種情況肯定包含在第一種情況裡。

class Solution {
	public:
		int rob(vector<int>& nums) {

			int n=nums.size();
			vector<int> dp(n,0);
			int imax=0;
			if(n<1) return 0;
			if(n==1) return nums[0];
			if(n==2) return max(nums[1],nums[0]);
			if(n==3) return max(nums[0],max(nums[1],nums[2]));
			if(n>=4) {
				//第一個不用
				dp[0]=0;
				dp[1]=nums[1];
				for(int i=2; i<n; i++) {
					dp[i]=max(dp[i-1],dp[i-2]+nums[i]);
				}
				imax=dp[n-1];

				//第一個用
				dp[0]=nums[0];
				dp[1]=max(nums[1],nums[0]);
				for(int i=2; i<n-1; i++) {
					dp[i]=max(dp[i-1],dp[i-2]+nums[i]);
				}
				imax=max(imax,dp[n-2]);
				return imax;
			}


		}
};