(这偷东西不太好吧!还得帮他算算怎么偷才能偷的更多,那我们岂不是帮凶?)
(所以呀,我不是不会做,我只是为了正义)
1、用动态规划做。
1)先建立一个数组themax,themax[i]表示偷到第i家人的最大获利。
2)初始化初始状态,themax[0]毫无疑问是nums[0],因为他当前就只能偷这一家;themax[1]为nums[0],nums[1]中最大的那个,因为偷到第1家的时候他可以选择不偷第0家而偷第1家(毕竟得挑贵的下手嘛)。
3)然后写出状态转移方程:themax[i]=opt(themax[i-1],themax[i-2]+nums[i])
因为这里假设前面偷到每一家的最大获利已经算好,所以当他来到第i家的时候,就得比较一下偷第i-1家的最大获利,偷第i-2家的最大获利和第i家的获利之和哪个更大,选择更大的那个作为偷到当前这家时最大获利。
4)然后用for循环去递推出最终的最大获利即可。
(虽然算出了怎么拿的最多,但是你算不到什么时候被捉,天网恢恢疏而不漏呀)
class Solution {
public:
int rob(vector<int>& nums) {
int thesize=nums.size();
if(thesize==1) return nums[0];
vector<int> themax(thesize,0);
themax[0]=nums[0];
themax[1]=max(nums[0],nums[1]);
for(int i=2;i<thesize;++i)
{
themax[i]=max(themax[i-1],themax[i-2]+nums[i]);
}
return themax[thesize-1];
}
int max(int a,int b)
{
return a>b?a:b;
}
};
2、优化一下。
由于每次递推只需要用到前两个的值,而且只需要得到偷到最后一家的最大获利即可。
而且在递推过程中,只用到了当前第i家的前两家的最大获利,所以我们可以只声明两个变量来记录前两家的最大获利即可,而不需要建立数组去保存偷到每一家的最大获利。
class Solution {
public:
int rob(vector<int>& nums) {
int thesize=nums.size();
if(thesize==1) return nums[0];
int max1=nums[0];
int max2=max(nums[0],nums[1]);
for(int i=2;i<thesize;++i)
{
max1=max(max2,max1+nums[i]);
myswap(max1,max2);
}
return max2;
}
int max(int a,int b)
{
return a>b?a:b;
}
void myswap(int& a,int& b)
{
a^=b;
b^=a;
a^=b;
}
};