ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

打家劫舍

2022-01-18 17:04:53  阅读:160  来源: 互联网

标签:return cur nums int 房子 打家劫舍 dp


This is the second version of House Robber.

题目描述:

You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed. All houses at this place are arranged in a circle. That means the first house is the neighbor of the last one. Meanwhile, adjacent houses have a security system connected, and it will automatically contact the police if two adjacent houses were broken into on the same night.

Given an integer array nums representing the amount of money of each house, return the maximum amount of money you can rob tonight without alerting the police.

样例输入:

输入一个整数n,表示这条街上房子的总数,接下来一行输入n个数mi,表示各房子中存储的金钱。

输出:

一个数,表示你可以偷取的最大价值。

样例输入:

3

1 2 3

样例输出:

3

提示:

1<=n<=100

0<=mi<=1000

这题不是最原始的打家劫舍,那个太简单了。这个是这一条街成了一个环,也就是说,如果偷了第一个房子里的钱,那就不能偷最后一个房子里的钱;如果偷了最后一个房子里的钱,就不能偷第一个房子里的钱。

那怎么办呢?一开始我想搞个flag标记,记录一下有没有偷第一个房子里的钱,但是搞了一会儿发现这样很难做出来,遂放弃。后来看了题解,恍然大悟!其实根本不用那么麻烦。

根据打家劫舍第一个版本,如果只有一间房子,我们肯定会偷,那么就是dp[0]=nums[0].如果有两家房子,那么dp[1]=max(nums[0],nums[1]).这两个初始条件的值放到这道题里仍然成立。好,现在我们来看看三间或三间以上房子的情况。如果是第一个版本,dp[i]表示的是到i这个位置截止共偷了多少钱,那么,到i这个位置,一定要么是从i-2来的,要么是从i-1来的,我们只需要取最大值就行了。所以dp[i]=max(dp[i-2]+nums[i],dp[i-1]).

现在放到这道题里面,第一个房子和第二个房子是相邻的,所以我们的动态规划方程有什么变化吗?没有。变的是偷取钱财的房子的范围。

如果我们偷第一间屋,那最后一间屋肯定就不能偷,此刻偷的范围就是从第一间房子到倒数第二间房子;如果偷的是最后一间屋子,那么偷的范围就是从第二件房子到最后一间房子。最后,我们只需要返回这二者的较大值就可以了。

为了卷死大多数人,决定不使用dp数组,太浪费内存了[狗头保命]。我们使用两个值来存,这期间不断更新就行。

下面是C++代码:

 1 #include <cstdio>
 2 #include <algorithm>
 3 #define N 1005
 4 using namespace std;
 5 int nums[N];
 6 int n;
 7 int range(int start, int end, int nums[])
 8 {
 9     int pre = nums[start];
10     int cur = nums[start + 1];
11     for (int i = start + 2; i < end; ++i) {
12         int next = max(pre + nums[i], cur);
13         pre = cur;
14         cur = next;
15     }
16     return max(cur, pre);
17 }
18 int rob(int nums[])
19 {
20     if (n == 1) {
21         return nums[0];
22     }
23     else if (n == 2) {
24         return max(nums[0], nums[1]);
25     }
26     return max(range(0, n - 1, nums), range(1, n, nums));
27 }
28 int main()
29 {
30     scanf_s("%d", &n);
31     for (int i = 0; i < n; ++i) {
32         scanf_s("%d", &nums[i]);
33     }
34     int ans = rob(nums);
35     printf("%d\n", ans);
36     return 0;
37 }

至于range函数为什么要返回pre和cur的最大值,额。。。这是我实践出来的结果,我也不知道为什么,反正你只返回一个肯定会出错,既然这样,那就返回二者较大的那个吧。

 

标签:return,cur,nums,int,房子,打家劫舍,dp
来源: https://www.cnblogs.com/EvanTheGreat/p/15818616.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有