题目:给一个整数数组,有正有负。找出数组最大和,条件是使用的元素不能有相邻 输出: 1)打印最大和 2)打印组成最大和的元素,用空格分隔 如果所有元素都是负数,最大和为最大的负数,要求时间复杂度为O(n) 例: 输入数组: -1,4,5,-2,-6,6 输出: 11 5 6 |
#include <iostream>
#include <vector>
#include <algorithm>
#include <limits>
using namespace std;
void MaxSum(vector<int> &vec)
{
/************************************************************************/
/* dp[i][j](i=1~n, j=0~1)表示取1~i这些数的最优解,其中j=0表示最后一个数不取,j=1表示最后一个数取。
dp[i][0] = max(dp[i-1][0], dp[i-1][1])
dp[i][1] = a[i] + dp[i-1][0]
显然这个dp是线性的。要输出解只要把状态转移的决策记录下来,追溯一下就行。 */
/************************************************************************/
vector<vector<int> > dp;
vector<int> b0;//记录前一个元素不取的解
vector<int> b1;//记录前一个元素取的解
vector<int> c0;;//记录当前一个元素不取的解
vector<int> c1;//记录当前一个元素取的解
vector<int> tmp;
int len=vec.size();
for (int i=0;i<=len;++i)
{
tmp.clear();
tmp.push_back(0);
tmp.push_back(0);
dp.push_back(tmp);
}
//初始化状态
dp[0][0]=0;
dp[0][1]=INT_MIN;
int maxE=INT_MIN;//记录数组的最大值,如果最大值小于0,则直接输出最大值
for (int i=0;i<len;++i)
{
dp[i+1][0]=max(dp[i][0],dp[i][1]);//当前元素不取
dp[i+1][1]=vec[i]+dp[i][0];//当前元素取,那么前一个元素必定不取
if (vec[i]>maxE)
{
maxE=vec[i];
}
if (dp[i][0]<dp[i][1])
{
c0=b1;
}else
c0=b0;
c1=b0;
c1.push_back(vec[i]);
b0=c0;
b1=c1;
}
if (maxE>0)
{
cout<<max(dp[len][0],dp[len][1])<<endl;
if (dp[len][0]<dp[len][1])
{
//c1
for (int i=0;i<c1.size();++i)
{
cout<<c1[i]<<' ';
}
}
else
{
//c0
for (int i=0;i<c0.size();++i)
{
cout<<c0[i]<<' ';
}
}
cout<<endl;
}else
{
//数组全部为负数
cout<<maxE<<endl;
cout<<maxE<<endl;
}
}
int main()
{
int n;
cin>>n;
int tmp;
vector<int> vec;
for (int i=0;i<n;++i)
{
cin>>tmp;
vec.push_back(tmp);
}
MaxSum(vec);
return 0;
}