题意:给出n天内的股票价格,要求两次买入卖出后获得最大的利润,要注意的是在第一次买入之后,必须要先卖出,然后才可以第二次买入,还要就是可以在同一天买入再卖出(一开始没想到)。
解题过程:题目和求最大子序列的和一样的原理,不过是要求解两个点的最大利润,所以需要双向dp求解,求解两边每个点的最大利润,求和后取最大值;
从左边dp,dpL[i]代表i前天中买卖一次最大的收益,price[i]表示第i天中的价格,minn表示前i天所有价格最小
dpL[i] = max{ pre[i−1]p , price[i]−minn }
从右面dp,也是同理,用dpR[i]表示从第j天到第n天买卖一次最大的收益,不过按照卖出要在买入那天的后面的天里以一个最大值卖出卖出,所以要用一个值maxx表示后j-n天的价格最大值。
dpR[i] = max{ dpR[j+1] , maxx−price[j] }
#include<iostream>
#include<cstdio>
using namespace std;
int price[100005],dpL[100005],dpR[100005];
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
int t;
cin>>t;
while(t--){
int n;
cin>>n;
for(int i=0;i<n;i++){
cin>>price[i];
}
int minn=price[0];dpL[0]=0;
for(int i=0;i<n;i++){
dpL[i]=max(dpL[i-1],price[i]-minn);
minn=min(minn,price[i]);
}
int maxx=price[n-1];dpR[n-1]=0;
for(int j=n-2;j>=0;j--){
dpR[j]=max(dpR[j+1],maxx-price[j]);
maxx=max(maxx,price[j]);
}
int sum=dpL[0]+dpR[0];
for(int i=0;i<n;i++){
sum=max(dpL[i]+dpR[i],sum);
}
cout<<sum<<endl;
}
}