POJ 8464 股票买卖 dp北大ACM/ICPC竞赛训练

Posted zhenghanghu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 8464 股票买卖 dp北大ACM/ICPC竞赛训练相关的知识,希望对你有一定的参考价值。

 主要不好想到定义问题状态,一开始想枚举第一次股票交易的卖出时间【这样O(1)处理第一次买入时间,logN处理第二次最大利益(第二次交易实际上是取最大值,所以可以用堆维护)】,但T*N*logN就tle了。

正解是dp1(i)代表1-i天一次交易的最大收益;再dp2(i)代表i-n天的最大收益。

以dp1(i)  = max( dp1(i-1) , a[i]-prev[i] ),prev是最小前缀,dp2同理。

这样O(n)做完。

 

难点在于怎么定义这个状态,因为一般来说会像我那么想i得是能提供一些信息的东西,而这里的dp(i)却不代表一定要在第i天做什么。所以这里的动态规划融合了【分治】的思想,要交易两次是吧,而且两次的时间不能有重叠,所以我就分开看。所以我们是从答案长什么样子入手,知道他们是分开的。那么一定能写成1-i天最大收益+i-n天最大收益的形式(不然他就不是最优解了),由此定义出的状态。所以像我之前对于dp的理解一样,我们定义状态如果直接定义出来了那么很好,不然的话要得到一些性质,并从性质入手去描述状态。

 1 #include<iostream>
 2 using namespace std;
 3 
 4 int a[100005],Prev[100005],post[100005],dp1[100005],dp2[100005];
 5                                         //dp1[i] 1-i的最大收益
 6                                         //dp2[i] i-n的最大收益 
 7 int main(){
 8     int t; cin>>t;
 9     while(t--){
10         int n,ans=0; cin>>n;
11         for(int i=1;i<=n;i++) scanf("%d",a+i);
12         for(int i=1;i<=n;i++) dp1[i]=dp2[i]=0;
13     
14         Prev[1]=a[1]; for(int i=2;i<=n;i++) Prev[i]=min(Prev[i-1],a[i]);//在第i天能买股票的最低价
15         post[n]=a[n]; for(int i=n-1;i>=1;i--) post[i]=max(post[i+1],a[i]);//第i天到第n天能卖出的最大值 
16 
17         for(int i=2;i<=n;i++) dp1[i]=max(dp1[i-1],a[i]-Prev[i]);
18         for(int i=n-1;i>=1;i--) dp2[i]=max( dp2[i+1],post[i]-a[i] );
19         for(int i=1;i<=n;i++) ans=max(ans,dp1[i]+dp2[i]);
20         
21         cout<<ans<<endl;
22     }
23     
24     return 0;
25 }

 

以上是关于POJ 8464 股票买卖 dp北大ACM/ICPC竞赛训练的主要内容,如果未能解决你的问题,请参考以下文章

noi 2.6_8464股票买卖(DP)

代码随想录算法训练营第四十九天| 121 买卖股票的最佳时机 122 买卖股票的最佳时机II

309. 最佳买卖股票时机含冷冻期 DP

暴力+DP:买卖股票的最佳时机

123. 买卖股票的最佳时机 III [dp]

[JavaScript 刷题] DP - 买卖股票的最佳时机,leetcode 121