题目链接:点击查看
题目描述:
假如你是一个劫匪,并且决定抢劫一条街上的房子,每个房子内的钱财数量各不相同。如果你抢了两栋相邻的房子,则会触发警报机关。求在不触发机关的情况下最多可以抢劫多少钱。
输入输出:
输入:[1,2,3,1] 输出:4
输入:[2,7,9,3,1] 输出:12
题目分析:
定义一个数组
dp
,
dp[i] 表示抢劫到第 i
个房子时,可以抢劫的最大数量。我们考虑
dp[i]
,此时可以抢劫的最大数量有两种可能,一种是我们选择不抢劫这个房子,此时累计的金额即为dp[i-1];另一种是我们选择抢劫这个房子,那么此前累计的最大金额只能是
dp[i-2]
,因为我们不能够抢劫第 i-1
个房子,否则会触发警报机关。因此本题的状态转移方程为
dp[i] = max(dp[i-1], nums[i-1] + dp[i-2])。
代码:
int rob(vector<int>&nums)
{
if(nums.empty())
return 0;
int n=nums.size();
vector<int>dp(n+1,0);
dp[1]=nums[0];//因为此前累计的金额为0,故抢劫第一个房子为第一步的最优解
for(int i=2;i<=n;++i)
{
dp[i]=max(dp[i-1],nums[i-1]+dp[i-2]);//若要抢劫第i个房子 在数组中即为nums[i-1]
}
return dp[n];
}
优化:根据dp思想,原问题的最优解来自于其子问题的最优解,故从第一步开始就要得到最优,所以 即可只用两个变量来储存初始状态 进行空间压缩
代码:
int rob(vector<int>&nums)
{
if(nums.empty())
return 0;
int n=nums.size();
if(n==1)
return nums[0];
int pre2=0,pre1=0,cur;
for(int i=0;i<n;++i)
{
cur=max(pre2+nums[i],pre1);
pre2=pre1;
pre1=cur;
}
return cur;
}