hdu3401
题意:给定t天的股票情况,要求出t天后最大的利润。
思路:单调队列优化dp
TIP:可能出现一直不买股票,最终利润为0的最优情况。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<map>
#include<set>
#include<algorithm>
#include<sstream>
#include<string>
using namespace std;
const int N=2007;
int t,ma,w;
int ap[N],bp[N],as[N],bs[N];
int dp[N][N];
struct data
{
int p,val;
}que[N*2],now;
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d",&t,&ma,&w);
for(int i=1;i<=t;i++)
{
scanf("%d%d%d%d",&ap[i],&bp[i],&as[i],&bs[i]);
}
for(int i=0;i<=t;i++)
{
for(int j=0;j<=ma;j++)
{
dp[i][j]=-99999999;
}
}
for(int i=1;i<=w+1;i++)
{
for(int j=0;j<=as[i];j++)
{
dp[i][j]=-ap[i]*(j);
}
}
for(int i=2;i<=t;i++)
{
for(int j=0;j<=ma;j++)
dp[i][j]=max(dp[i][j],dp[i-1][j]);
if(i<=w+1)
continue;
int front,rear;
front=0;
rear=0;
for(int j=0;j<=ma;j++)
{
now.p=j;
now.val=dp[i-w-1][j]+ap[i]*j;
while(front<rear&&que[rear-1].val<now.val)
{
rear--;
}
que[rear++]=now;
while((front==-1)||(front<rear&&que[front].p+as[i]<j))
front++;
dp[i][j]=max(dp[i][j],que[front].val-ap[i]*j);
}
front=0;
rear=0;
for(int j=ma;j>=0;j--)
{
now.p=j;
now.val=dp[i-w-1][j]+bp[i]*j;
while(front<rear&&que[rear-1].val<now.val)
{
rear--;
}
que[rear++]=now;
while((front==-1)||(front<rear&&que[front].p-bs[i]>j))
front++;
dp[i][j]=max(dp[i][j],que[front].val-bp[i]*j);
}
}
int ans=0;
for(int i=0;i<=ma;i++)
{
ans=max(ans, dp[t][i]);
}
printf("%d\n",ans);
}
return 0;
}