打家劫舍2

描述

你是一个经验丰富的小偷,准备偷沿湖的一排房间,每个房间都存有一定的现金,为了防止被发现,你不能偷相邻的两家,即,如果偷了第一家,就不能再偷第二家,如果偷了第二家,那么就不能偷第一家和第三家。沿湖的房间组成一个闭合的圆形,即第一个房间和最后一个房间视为相邻。

给定一个长度为n的整数数组nums,数组中的元素表示每个房间存有的现金数额,请你计算在不被发现的前提下最多的偷窃金额。

数据范围:数组长度满足 1≤n≤2×10^5 1≤nums[i]<=5000

输入描述:

第一行输入一个正整数 n ,表示数组的长度。

第二行输入 n 个正整数,表示每个房间存有的现金。

输出描述:

输出最多的偷窃金额

示例1

输入:

4
1 2 3 4

输出:

6

说明:

最优方案是偷第 2 4 个房间       

示例2

输入:

3
1 3 6

输出:

6

说明:

由于 1 和 3 是相邻的,因此最优方案是偷第 3 个房间       

这是一道经典的动态规划问题,可以使用 dp 数组记录偷到第 i 个房间时的最大金额,状态转移方程为:

//如果我们去偷了第i个房间,那么第i-1号房间就不能偷,如果我们不去第i号房间,那么我们可以去//i-1号房间。得出

dp[i] = max(dp[i-2]+nums[i], dp[i-1])

由于我们去偷了一号就不能去偷最后一号,所以可以分为两种情况,第一种是偷1号房间,一种是偷最后的房间而不去第一个房间。设dp为不偷一号房间,dp2为不偷最后的房间。

#include <stdio.h>
long long int max(long long int a,long long int b){
    return a>b ? a :b;
}
long long int my_(long long int *a,long long int n){
    int dp1[200001],dp2[200001];
    dp1[0]=0;dp1[1]=0;    //保证不偷一号房间
    dp2[0]=0;dp2[1]=a[1]; //此时的一号房间有钱,可以去偷嘿嘿。
//不偷第一个
    for(long long int i=2;i<=n;i++){

        dp1[i]=a[i];
        dp1[i]=max(dp1[i-2]+dp1[i],dp1[i-1]);
    }
//不偷最后一个
for(long long int i=2;i<=n-1;i++){
      dp2[i]=a[i];
        dp2[i]=max(dp2[i-2]+dp2[i],dp2[i-1]);
}
long long int last=max(dp1[n],dp2[n-1]);    //找到这两种情况偷的最多的钱的情况
return last;
}
int main() {
    long long int n,i,a[200001];
    scanf("%lld",&n);
    
    for(i=1;i<=n;i++){
        scanf("%lld",&a[i]);
    }
    long long int test=my_(a,n);
  printf("%lld",test);
}

其中,dp2[]表示可以偷第1 个房间而不偷最后一个房间,dp1[] 表示不偷第 i 个房间而可以偷最后一个。由于是一个闭合的圆形,所以需要分别计算不偷第一个房间和不偷最后一个房间的情况,最终结果取两种情况的最大值。

  • 15
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
打家劫舍2是一道动态规划问题,可以使用类似于打家劫舍1的思路解决。不同的是,在这道题目中,房屋排列成了一个环形,也就是说第一个房屋和最后一个房屋是相邻的。因此,我们需要分别计算偷第一个房屋和不偷第一个房屋两种情况下的最大收益,最后取两种情况中的较大值即可。 以下是Python的代码实现: ```python class Solution: def rob(self, nums: List[int]) -> int: if not nums: return 0 if len(nums) == 1: return nums[0] return max(self.robRange(nums, 0, len(nums) - 2), self.robRange(nums, 1, len(nums) - 1)) def robRange(self, nums: List[int], start: int, end: int) -> int: n = len(nums) dp_i_1, dp_i_2 = 0, 0 dp_i = 0 for i in range(end, start - 1, -1): dp_i = max(dp_i_1, nums[i] + dp_i_2) dp_i_2 = dp_i_1 dp_i_1 = dp_i return dp_i ``` 在这个解法中,`robRange` 函数用于计算不同范围内的最大收益。我们使用 `dp_i_1` 和 `dp_i_2` 分别表示前两个子问题的最大收益,`dp_i` 表示当前子问题的最大收益。在每次迭代中,我们根据状态转移方程 `dp[i] = max(dp[i-1], nums[i] + dp[i-2])` 来更新 `dp_i`、`dp_i_1` 和 `dp_i_2` 的值。最后返回 `dp_i` 即可得到该范围内的最大收益。 在 `rob` 函数中,我们分别计算偷第一个房屋和不偷第一个房屋两种情况下的最大收益,并取两种情况中的较大值返回。其中 `robRange(nums, 0, len(nums) - 2)` 表示偷第一个房屋的情况,`robRange(nums, 1, len(nums) - 1)` 表示不偷第一个房屋的情况。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值