动态规划小练
昨天早上有道贪心题我妄想用dp来做,想了O(n)的算法想了巨久,然后没想出来草草打了一个n2的DP然后就十分难受。于是就去练了一下水DP以提升自己DP水平。
昨天那道dp
量化交易
【问题描述】
applepi训练了一个可以自动在股票市场进行量化交易的模型。通常来说,训练了一个可以自动在股票市场进行量化交易的模型。你懂得就好比一架印钞机。不过为了谨慎起见applepi还是想先检查一下模型的效果。
applpie收集了“塞帕思股份收集了“塞帕思股份(surpass)”在最近的连续”在最近的连续N天内的价格。在每一天内的价格。在每一天中,他可以做如下事情之一:
1. 睡(把)觉妹。睡(把)觉妹。
2. 以当天的价格作为成交买入1股“塞帕思”的票。
3. 以当天的价格作为成交卖出1股“塞帕思”的票。
最初applepi不持有该股票。现在你需要计算出最优策略下,不持有该股票。现在你需要计算出最优策略下,N天后applepi能够获得的最大利润。为了维护森林和平,本着清仓甩锅原则在N天的交易结束后applepi也不能持有“塞帕思”的股票。
【输入格式】
每个测试点包含若干组数据,以EOF结尾。对于每组数据:
第一行1个整数N。
第二行N个正整数,相邻两之间用1个空格隔开,表示每一天股票的价格。
一开始以为该题跟某经典dp美元换马克异曲同工,可它毕竟是二中的联考,于是草草打了一个n2DP
f[i][j]表示前i天拥有j股票的最优利益,从上一轮买或者卖或者什么都不干过继过来,要注意的是数组一开始要置的很小,大概-9999999吧,如果不小会错,为此我调了好久,还不停质疑dp的正确性,哎。
#include<iostream>
#include<cstdio>
using namespace std;
int n,a[100005];
long long f[1005][1005];
#define INF 100000000000
int main()
{
int k=0;
while (cin>>n)
{
k++;
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
for (int i=-1;i<=n;i++) f[0][i]=-INF;
f[0][0]=0;
for (int i=1;i<=n;i++)
for (int j=0;j<=n;j++)
{
if (j>i||j>n-i)
{
f[i][j]=-INF;
continue;
}
f[i][j]=max(f[i-1][j-1]-a[i],f[i-1][j+1]+a[i]);
f[i][j]=max(f[i][j],f[i-1][j]);
}
// for (int i=1;i<=n;i++)
// {
// for (int j=0;j<=n;j++) cout<<f[i][j]<<' ';
// cout<<'\n';
// }
printf("Case #%d: %d\n",k,f[n][0]);
}
}
因为这道题一开始想的是O(n)DP,所以是想维护两个数组,一个规划资金,另一个规划股票的利益但是我真的想不出来怎么保证最后把股票卖光而且不知道如何维护最优卖出日期,
万万没想到正解是……贪心+堆。。。用一个堆去做一个后悔