基于动态规划的思想我们再来做几个练习
练习2:在一组数中选择几个数字使其加起来和最大,但是选中的几个数字不能相邻,求最大的和
以以下这组数据举栗子
我们依旧是之前的思想:选或者不选!!!!!!
依旧是最优解OPT(i)代表到第i个元素最优解是什么
+代表选择第i个 -代表不选择第i个
我们发现这个展开图中依旧出现了重叠子问题 ,比如OPT(3)和OPT(4),那么我们就可以采用动态规划,避免使用递归重复计算
OPT(i-2) + arr [i] ; //选择第i个元素
OPT(i) = max
OPT(i-1) //不选第i个元素
这就是该问题的递归式,那么递归出口应该是什么呢?
对了,当i=0时,OPT(i)=arr[0] 或者当i=1时,OPT(1) = max ( arr[0], arr[1] );
okkkkk,问题分析清楚了,上代码
//递归版本 时间复杂度O(2^n)
int RecOpt(int *arr,int i)
{
if(i==0) return arr[0];
else if(i==1) return max(arr[0],arr[1]);
else return max(RecOpt(arr,i-2)+arr[i],RecOpt(arr,i-1));
}
int main()
{
int arr[]={1,2,4,1,7,8,3};
int len=sizeof(arr)/sizeof(arr[0]);
cout<<RecOpt(arr,len-1)<<endl;
}
接着看非递归版本
int NotRecOpt(int *arr,int i)
{
if(i<0||arr==NULL)
return -1;
if(i==0)
return arr[0];
vector<int> maxsum(i+1);
maxsum[0]=arr[0];
maxsum[1]=max(arr[0],arr[1]);
for(int j=2;j<=i;j++)
maxsum[j]=max(maxsum[j-1],maxsum[j-2]+arr[j]);
return maxsum[i];
}