2017.9.9 股票交易 思考记录
2017-09-09 22:53
232 查看
这题、只要找到了突破口就好做了
首先最好想的是n^3的dp、f【i】【j】表示在第i天有j张票的最大收益、枚举卖出和买入的个数即可
但我们需要一个n^2的做法
所以我们就可以分析题目的特点:
这个题有一个前w天的限制,但w=0时它又与普通dp无异,所以不是突破口,它只是刷一下存在感
然后对于每一天都有收益,,如果把他想成限制,那他就比所有的天都一样要麻烦;
但如果把他想成放宽,则他这一天里,每一张的买入和卖出是一样的
所以我们考虑如何用一天内相同量来简化决策
对于两个可取的决策: f[j]+(j-i)*v 和 f[k]+(k-i)*v
如果i+1,即到了多一张票数:
f[j]+(j-i-1)*v & f[k]+(k-i-1)*v
他们都只多出了一个1*v
所以这一种票数的决策其实可以沿用上一张票数的情况
所以我们加入合法的、退出不合法的
新加入的比以前加入的晚被弹出
每加入一个新节点就可以删除旧节点
就是单调队列了
码(单调队列不熟、写的极其难看):
#include<iostream>
#include<cstdio>
using namespace std;
int n,sx,w,i,j,f[2002][2002],g1[2002],g2[2002],ans,c,v,sc,sv;
int main()
{
scanf("%d%d%d",&n,&sx,&w);
w++;
for(i=1;i<=sx;i++)
f[0][i]=-1000000009;
for(i=1;i<=n;i++)
{
scanf("%d%d%d%d",&c,&v,&sc,&sv);
for(j=0;j<=sx;j++)
f[i][j]=f[i-1][j];//继承相当于放弃这一天的买卖机会
int z1=1,z2=1,z3=1,z4=1;
g1[1]=1;
int qi=2;
g2[1]=0;
for(j=0;j<=sx;j++)
{
//卖的出队
if(g1[z1]<=j)++z1;//卖的比之后的相等、小就被迫出队
for(;qi<=min(j+sv,sx);qi++)//卖的 加入队列
{
while(z1<=z2&&(f[max(i-w,0)][g1[z2]]+(g1[z2]-j)*v<f[max(i-w,0)][qi]+(qi-j)*v))--z2;
g1[++z2]=qi;
}
if(j!=sx)f[i][j]=max(f[i][j],f[max(i-w,0)][g1[z1]]+(g1[z1]-j)*v);
if(j!=0)
{
if(g2[z3]<j-sc)++z3;//买的出队
if(j!=1){while(z3<=z4&&f[max(i-w,0)][g2[z4]]-(j-g2[z4])*c<f[max(i-w,0)][j-1]-c )z4--;//买的入队
g2[++z4]=j-1;}
f[i][j]=max(f[i][j],f[max(i-w,0)][g2[z3]]-(j-g2[z3])*c);
}
// cout<<f[i][j]<<" ";
}
// cout<<endl;
}
for(i=0;i<=sx;i++)
ans=max(ans,f
[i]);
printf("%d",ans);
}
首先最好想的是n^3的dp、f【i】【j】表示在第i天有j张票的最大收益、枚举卖出和买入的个数即可
但我们需要一个n^2的做法
所以我们就可以分析题目的特点:
这个题有一个前w天的限制,但w=0时它又与普通dp无异,所以不是突破口,它只是刷一下存在感
然后对于每一天都有收益,,如果把他想成限制,那他就比所有的天都一样要麻烦;
但如果把他想成放宽,则他这一天里,每一张的买入和卖出是一样的
所以我们考虑如何用一天内相同量来简化决策
对于两个可取的决策: f[j]+(j-i)*v 和 f[k]+(k-i)*v
如果i+1,即到了多一张票数:
f[j]+(j-i-1)*v & f[k]+(k-i-1)*v
他们都只多出了一个1*v
所以这一种票数的决策其实可以沿用上一张票数的情况
所以我们加入合法的、退出不合法的
新加入的比以前加入的晚被弹出
每加入一个新节点就可以删除旧节点
就是单调队列了
码(单调队列不熟、写的极其难看):
#include<iostream>
#include<cstdio>
using namespace std;
int n,sx,w,i,j,f[2002][2002],g1[2002],g2[2002],ans,c,v,sc,sv;
int main()
{
scanf("%d%d%d",&n,&sx,&w);
w++;
for(i=1;i<=sx;i++)
f[0][i]=-1000000009;
for(i=1;i<=n;i++)
{
scanf("%d%d%d%d",&c,&v,&sc,&sv);
for(j=0;j<=sx;j++)
f[i][j]=f[i-1][j];//继承相当于放弃这一天的买卖机会
int z1=1,z2=1,z3=1,z4=1;
g1[1]=1;
int qi=2;
g2[1]=0;
for(j=0;j<=sx;j++)
{
//卖的出队
if(g1[z1]<=j)++z1;//卖的比之后的相等、小就被迫出队
for(;qi<=min(j+sv,sx);qi++)//卖的 加入队列
{
while(z1<=z2&&(f[max(i-w,0)][g1[z2]]+(g1[z2]-j)*v<f[max(i-w,0)][qi]+(qi-j)*v))--z2;
g1[++z2]=qi;
}
if(j!=sx)f[i][j]=max(f[i][j],f[max(i-w,0)][g1[z1]]+(g1[z1]-j)*v);
if(j!=0)
{
if(g2[z3]<j-sc)++z3;//买的出队
if(j!=1){while(z3<=z4&&f[max(i-w,0)][g2[z4]]-(j-g2[z4])*c<f[max(i-w,0)][j-1]-c )z4--;//买的入队
g2[++z4]=j-1;}
f[i][j]=max(f[i][j],f[max(i-w,0)][g2[z3]]-(j-g2[z3])*c);
}
// cout<<f[i][j]<<" ";
}
// cout<<endl;
}
for(i=0;i<=sx;i++)
ans=max(ans,f
[i]);
printf("%d",ans);
}
相关文章推荐
- 2017.9.9 堵塞的交通 思考记录
- 1171 股票交易
- 2017.8.5 One-Dimensional 思考记录
- 2017.10.19 起床困难综合征 思考记录
- 20160130交易记录
- 推荐一种新的思考、记录方法“思维导图”
- 简图记录-人月神话-编程产品开发的问题与思考
- leetcode 122. Best Time to Buy and Sell Stock II-股票交易|贪心算法
- 2017.8.20 后缀自动机(p3804) 思考记录
- 2017.4.23 税收与补贴问题 思考记录
- 银行管理系统 实现用户注册 登录 存、取款 交易记录查询和修改用户信息等功能
- 今天开始记录一些买卖股票的记录心得
- 量化交易----编程实例:爬取标普500指数股票数据
- 2017.5.5 小朋友的数字 思考记录
- 2017.9.4 Nim 思考记录
- 股票操作记录 2011.2.17
- DP——BZOJ1855/Luogu2569 [SCOI2010]股票交易
- cocos2dx-lua里面class的实现的一些问题记录和思考
- BZOJ 1855 [Scoi2010]股票交易 单调队列优化DP