题目来源于:洛谷
题目本质:动态规划,单调队列
解题思路:
方程f[i][j]表示第 i 天结束后,手里剩下 j 股的最大利润,则不买不卖:f[i][j]=f[i-1][j]。
买入:f[i][j]=max{f[i-w-1][k]+k*ap[i]}-ap[i]*j
卖出:f[i][j]=max{f[i-w-1][k]+k*bp[i]}-bp[i]*j
完整代码如下:
#include<bits/stdc++.h>
using namespace std;
const int N=2010;
int t,maxp,w;
int ap[N],bp[N],as[N],bs[N];
int f[N][N];
int q[10000],qhead=1,qtail=0;
int main(){scanf("%d%d%d",&t,&maxp,&w);for(int i=1;i<=t;i++){scanf("%d%d%d%d",&ap[i],&bp[i],&as[i],&bs[i]);}memset(f,-0x7f,sizeof(f));for(int i=0;i<=t;i++){f[i][0]=0;}for(int i=1;i<=t;i++){for(int j=0;j<=as[i];j++){f[i][j]=-ap[i]*j;}for(int j=maxp;j>=0;j--){f[i][j]=max(f[i][j],f[i-1][j]);}if(i-w-1>=0){qhead=1;qtail=0;for(int j=0;j<=maxp;j++){while(qhead<=qtail&&q[qhead]<j-as[i]){qhead++;}while(qhead<=qtail&&f[i-w-1][j]+ap[i]*j>=f[i-w-1][q[qtail]]+ap[i]*q[qtail]){qtail--;}q[++qtail]=j;if(qhead<=qtail){f[i][j]=max(f[i][j],f[i-w-1][q[qhead]]-ap[i]*(j-q[qhead])); }} qhead=1;qtail=0;for(int j=maxp;j>=0;j--){while(qhead<=qtail&&q[qhead]>j+bs[i]){qhead++;}while(qhead<=qtail&&f[i-w-1][j]+bp[i]*j>=f[i-w-1][q[qtail]]+bp[i]*q[qtail]){qtail--;}q[++qtail]=j;if(qhead<=qtail){f[i][j]=max(f[i][j],f[i-w-1][q[qhead]]+bp[i]*(q[qhead]-j));}} } }int ans=0;for(int i=0;i<=maxp;i++){ans=max(f[t][i],ans);}printf("%d",ans);return 0;
}