题面描述
思路
这道题DP的很明显啊(可惜我就是不会写啊)
提前声明:
这里的 n n n为 T T T, m m m为 M a x P MaxP MaxP, t t t为 W W W, a a a为 A P i AP_i APi, c c c为 B P i BP_i BPi,b为 A S i AS_i ASi, d d d为 B S i BS_i BSi
首先根据题意,因为 i i i天买了股票, i + t i+t i+t天也不能买股票,干脆 t + + t++ t++,
状态转移方程:
F
i
,
j
=
{
F
i
−
1
,
j
−
a
∗
j
(
j
≤
b
)
F
i
−
t
,
k
−
a
∗
j
+
a
∗
k
(
0
≤
k
≤
j
−
1
&
j
−
k
≤
b
)
F
i
−
t
,
k
+
c
∗
k
−
c
∗
j
(
j
+
1
≤
k
≤
m
&
k
−
j
≤
d
)
}
F_{i,j}=\begin{Bmatrix} F_{i-1,j}\\ -a*j(j\le b)\\ F_{i-t, k}-a*j+a*k(0\le k\le j-1\And j-k\le b)\\ F_{i-t,k}+c*k-c*j(j+1\le k\le m\And k-j\le d)\end{Bmatrix}
Fi,j=⎩⎪⎪⎨⎪⎪⎧Fi−1,j−a∗j(j≤b)Fi−t,k−a∗j+a∗k(0≤k≤j−1&j−k≤b)Fi−t,k+c∗k−c∗j(j+1≤k≤m&k−j≤d)⎭⎪⎪⎬⎪⎪⎫
第一条方程就是这天啥都不干(真是个有趣的家伙)。
第二条方程就是在前 b b b天买进 j j j张股票。
第三条方程就是在前 i − t i-t i−t天已经买了k张股票,在 i i i天再买 i − k i-k i−k张股票。
第三条方程就是在前 i − t i-t i−t天买了k张股票,在 i i i天卖剩 j j j张股票。
这种 D P DP DP已经可以拿下 70 70 70分了,
然后呢?(就T的没边了)
观察许久,我发现貌似第
3
3
3、
4
4
4个方程可以单调队列优化。
(因为它们具有单调性)
踢队头很好写,踢队尾可以观察发现有共性:
F i − t , k + c ( a ) ∗ k F_{i-t,k}+c(a)*k Fi−t,k+c(a)∗k
因此我们就可以以这个为标准,踢掉不优的队尾。
while(l<=r&&f[i-t][j]+a*j>=f[i-t][q[r]]+a*q[r])--r;
while(l<=r&&f[i-t][j]+c*j>=f[i-t][q[r]]+c*q[r])--r;
貌似这道题就结束了?
AC code
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<cmath>
#define gc getchar()
using namespace std;
const int N=2010;
inline void qr(int &x)
{
x=0;int f=1;char c=gc;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc;}
while(c>='0'&&c<='9'){x=x*10+(c^48);c=gc;}
x*=f;
}
void qw(int x)
{
if(x<0)x=-x,putchar('-');
if(x/10)qw(x/10);
putchar(x%10+48);
}
int f[N][N];
int q[N];
int main()
{
int n,m,t;qr(n),qr(m),qr(t);t++;
f[0][0]=-N*N;for(int j=1;j<=m+1;j++)f[0][j]=f[0][j-1];
for(int i=1;i<=n;i++)
{
int a,b,c,d,l,r;
qr(a),qr(c),qr(b),qr(d);
for(int j=0;j<=m+1;j++)f[i][j]=f[i-1][j];
for(int j=0;j<=b;j++)f[i][j]=max(f[i][j],-a*j);
if(i>t)
{
l=1;r=0;q[1]=0;
for(int j=0;j<=m;j++)
{
while(l<=r&&q[l]<j-b)++l;
f[i][j]=max(f[i][j],f[i-t][q[l]]-a*j+a*q[l]);
while(l<=r&&f[i-t][j]+a*j>=f[i-t][q[r]]+a*q[r])--r;
q[++r]=j;
}
l=1;r=0;q[1]=m+1;
for(int j=m;j>=0;j--)
{
while(l<=r&&q[l]-j>d)++l;
f[i][j]=max(f[i][j],f[i-t][q[l]]+c*q[l]-c*j);
while(l<=r&&f[i-t][j]+c*j>=f[i-t][q[r]]+c*q[r])--r;
q[++r]=j;
}
}
}
qw(f[n][0]);puts("");
return 0;
}