[SCOI2010] 股票交易
[SCOI2010] 股票交易
单调队列优化 dp 的经典问题。
分析
dp 加单调队列优化。
首先,不难想到是动态规划,看数据范围,可以支持
第一维肯定是天数,但是显然不够,所以第二维可以是手中的股票数。设
初始状态,手中并没有任何股票,在某一天
然后每天只有三种情况,什么都不做,只买,只卖。
- 什么都不做,就是和上一天的状态一样,所以:
- 只买,因为要间隔至少
天,所以可以从 天转移过来,但是因为上一种情况已经将 的状态都能转移到第 天,设第 天手中有 支股票。因为要买入 支股票,再考虑限制,所以 ,所以:
- 只卖,和上一种情况差不多,要卖出
支股票,考虑限制 ,所以:
因为
考虑一下边界状况:
以情况
在情况
code
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
using namespace std;
typedef long long ll;
const int N=2005;
int n,m,w;
int f[N][N],q[N];
void solve()
{
cin>>n>>m>>w;
memset(f,-0x3f,sizeof f);
for(int i=1;i<=n;i++)
{
int ap,bp,as,bs;
cin>>ap>>bp>>as>>bs;
for(int j=0;j<=as;j++) f[i][j]=-ap*j;
for(int j=0;j<=m;j++) f[i][j]=max(f[i][j],f[i-1][j]);
if(i<=w) continue;
int l=1,r=0,k=-1;
for(int j=0;j<=m;j++)
{
while(k<j-1)
{
k++;
while(l<=r&&f[i-w-1][q[r]]+q[r]*ap<=f[i-w-1][k]+k*ap) r--;
q[++r]=k;
}
while(l<=r&&q[l]<j-as) l++;
if(l<=r) f[i][j]=max(f[i][j],f[i-w-1][q[l]]+q[l]*ap-j*ap);
}
l=1,r=0,k=0;
for(int j=0;j<=m;j++)
{
while(k<j+bs&&k<m)
{
k++;
while(l<=r&&f[i-w-1][q[r]]+q[r]*bp<=f[i-w-1][k]+k*bp) r--;
q[++r]=k;
}
while(l<=r&&q[l]<j+1) l++;
if(l<=r) f[i][j]=max(f[i][j],f[i-w-1][q[l]]+q[l]*bp-j*bp);
}
}
int ans=0;
for(int i=0;i<=m;i++) ans=max(ans,f[n][i]);
cout<<ans<<'\n';
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
#endif
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
solve();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」