题目:有n个房子,排成一排,已知每个房子的糖果数目,要求不能在相邻两个房子里偷糖果,这样会暴露自己,走一遍所有屋子,最多能拿多少颗糖果
思路:动态规划。遍历的时候分两种情况,偷第一个房子的糖果,和不偷第一个房子的糖果,前者总糖果数=第一个房子的糖果数+剩余房子的最大糖果数; 后者总糖果数=除了第一个房子的其余房子可得的最大糖果数。
用递归算法解决该问题时,会产生很多重叠子问题,效率比较差,一般用非递归算法。下面给出了这两种方法的代码实现:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
//非递归
int NiceGetCandies(vector<int>&vec)
{
int n=vec.size();
vector<int>vv(n);//最优解数组:存储截止当前下标的房子时,可偷到的糖果数
vv[0]=vec[0];
vv[1]=max(vec[0],vec[1]);
for(int i=2;i<n;++i)
{
int a=vv[i-2]+vec[i];//偷了0号房子
int b=vv[i-1];//没偷0号房子
vv[i]=max(a,b);
}
return vv[n-1];
}
int main()
{
int n;
cin>>n;
vector<int>vec(n);
for(int i=0;i<n;i++)
{
int k;
cin>>k;
vec.push_back(k);
}
int res=NiceGetCandies(vec);
cout<<res<<endl;
return 0;
}
/*
//递归
int GetCandies(vector<int> &vec,int n)//n为最后一个房子的下标
{
if(n==0) return vec[0];
else if(n==1) return max(vec[0],vec[1]);
else
{
int a=GetCandies(vec,n-2)+vec[n];//选n号下标的房子
int b=GetCandies(vec,n-1);//不选n号房子
return max(a,b);
}
}
int main()
{
int n;
cin>>n;
vector<int>vec(n);
for(int i=0;i<n;i++)
{
cin>>vec[i];
}
int res=GetCandies(vec,0,0);
cout<<res<<endl;
return 0;
}
*/
运行结果如图: