OpenJ_Bailian - 4121 双向建dp

题意:给出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;
	}
}

 

猜你喜欢

转载自blog.csdn.net/samscream/article/details/81916627