打家劫舍
leetcode题目链接:198. 打家劫舍
考虑下标i(包括i)以内的房屋,最多可以偷窃的金额为dp[i]。
决定dp[i]的因素就是第i房间偷还是不偷。
如果偷第i房间,那么dp[i] = dp[i - 2] + nums[i] ,即:第i-1房一定是不考虑的,找出 下标i-2(包括i-2)以内的房屋,最多可以偷窃的金额为dp[i-2] 加上第i房间偷到的钱。
如果不偷第i房间,那么dp[i] = dp[i - 1],即考虑i-1房,(注意这里是考虑,并不是一定要偷i-1房)
然后dp[i]取最大值,即dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]);
从递推公式dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]);可以看出,递推公式的基础就是dp[0] 和 dp[1]
从dp[i]的定义上来讲,dp[0] 一定是 nums[0],dp[1]就是nums[0]和nums[1]的最大值即:dp[1] = max(nums[0], nums[1]);
int main()
{
int n;
cin >> n;
vector<int>dp(n, 0), money(n, 0);
for (int i = 0; i < n; i++)
{
cin >> money[i];
}
dp[0] = money[0];
dp[1] = max(money[0], money[1]);
for (int i = 2; i < n; i++)
{
dp[i] = max(dp[i - 1], dp[i - 2] + money[i]);
}
cout << dp[n - 1] << endl;
return 0;
}
打家劫舍II
leetcode题目链接:213. 打家劫舍 II
这道题目与上一道相似,只是换成环。
房间环状排列 意味着第一间和最后一间不能同时选择,因此我们可以分成两种情况来讨论:
- 1、不偷窃最后一间房间,那么问题转化为偷窃
1
号到i - 1
号房间所能获得的最高金额。 - 2、不偷窃第一间房间,那么问题转化为偷窃
2
号到i
号房间所能获得的最高金额。 - 把两种情况分为两个数组分别讨论取最大值即可
int n;
int rob(vector<int>& money)
{
vector<int>dp(n, 0);
if (money.size() == 1)
return money[0];
else
{
dp[0] = money[0];
dp[1] = max(money[0], money[1]);
for (int i = 2; i < money.size(); i++)
{
dp[i] = max(dp[i - 1], dp[i - 2] + money[i]);
}
return dp[money.size() - 1];
}
}
int main()
{
cin >> n;
vector<int>money(n, 0);
for (int i = 0; i < n; i++)
{
cin >> money[i];
}
if (n == 1)
{
cout << money[0] << endl;
return 0;
}
vector<int>money1(money.begin(), money.end() - 1);//抢头,不抢尾
vector<int>money2(money.begin() + 1, money.end());//抢尾,不抢头
int ret1 = rob(money1);
int ret2 = rob(money2);
cout << (ret1 > ret2 ? ret1 : ret2) << endl;
return 0;
}