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

213. 打家劫舍 II -M

213. 打家劫舍 II

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

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

示例 1:

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

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

    相比 198. 打家劫舍 這道題增加了子集中的最優,198那道題,因為  
    都是正整數,所以{0,i}的集合加和求解就好,213增加了環,所以i=s-1  
    時,要看集合{1,i-2}的最大值,即無法用原來的動態一維陣列dp,這  
    一要用二維dp,要用到
    dp[0][i]=dp[0][i-2],i=s-1時,dp[0][i]=dp[1][i-2]
    

    如果題目中加了負數,那難度就又提高了。

  • code

package main

import "fmt"

func rob(nums []int) int {
	s:=len(nums)
	if s==0{
		return 0
	}
	dp:=
make([][]int,len(nums)) for i:=0;i<s;i++{ dp[i]=make([]int,s) dp[i][i]=nums[i] if i+1<s{ dp[i][i+1]=nums[i+1] if dp[i][i+1]<dp[i][i]{ dp[i][i+1]=dp[i][i] } } } for size:=3;size<=s;size++{ for i:=0;i<s-size+1;i++{ if i+size==s{ dp[i][i+size-1]=nums[i+size-
1]+dp[i+1][i+size-3] }else{ dp[i][i+size-1]=nums[i+size-1]+dp[i][i+size-3] } if dp[i][i+size-1]<dp[i][i+size-2]{ dp[i][i+size-1]=dp[i][i+size-2] } } } return dp[0][s-1] } func main(){ fmt.Println(rob([]int{1,2,3,1})) fmt.Println(rob([]int{2,3,2})) fmt.Println(rob([]int{3,2})) }