嚴重鄙視這一題,弄了N復雜的一個題意。。。做了好多天都沒想法,今天終于看著題解把它A掉了。。
其實單調隊列如果再沒有明顯的 max(i,i+K) 的情況下。。很難想得到。這個題目就是。
題意是說一個人跟政府關系很好。知道了下面T天每天的股票價格。但是XX告訴他,兒子啊,我告訴你啊,你買股票要這么買,要不會被抓的。你手上的股票數最多不能超過maxP,而且某一天買賣之后,下次買賣的時間必須延后W天,你懂的。好了,下面告訴你T天的價格,你自己賺錢去吧。
這題的樸素的DP方程是這樣的: res[i][j] = res[i-W-1][k] + 買入或賣出的代價 ( j-ASi<=k <=j+BSi )
有人會問為什么只枚舉了i-W-1天呢?前面的日子呢?額。。。前面的日子已經歸到i-W-1天啦。
好了,這破題。狀態復雜度: T*maxP,決策復雜度maxP。無懸念的超時了。
別人說用單調隊列優化就單調隊列優化吧。
我們可以這樣想:假如i-w-1天那家伙持有的股票根據那天股票的價格換成了錢,就是都虛擬換成r[i-w-1][0],這樣,我們可以知道,我們不會選擇錢少的決策的,因為我們現在得j是固定的,當換算后的錢多的時候,無論怎樣決策都比錢少的好。。,好了,著就變成了第二句話那樣的模型了,直接換算出來,弄個丑陋的單調隊列出來,然后唧唧歪哇一大堆。
下面是代碼,寫的比較長,比較亂。糾結。。。。糾結。。。。
//單調隊列用法:求一段序列里的最值。 加上決策有序
//這個題 : 決策的時候,把持有的股票數轉化出來,可知當決策為 max(res[i-W-1][j-ASi],res[i-W-1][j+BSi]+k*BAi,BPi)時,


#include <stdio.h>
#include <string.h>
#define inf 900000

typedef struct


{
int APi,BPi,ASi,BSi;
}node;

typedef struct


{
int pos;
int res;
}qe;
int qhead,qtail;
qe queue[410010];
node data[2010];

int res[2010][2010];//第i天擁有j的股票賺的最多的錢

int T,W,maxP;

int max(int i,int j)


{
if(i > j) return i;
return j;
}

int main()


{
int testcase,i,j,k;
scanf("%d",&testcase);
while(testcase--)

{
int ans = 0;
scanf("%d%d%d",&T,&maxP,&W);
for(i=1;i<=T;i++)

{
scanf("%d%d%d%d",&data[i].APi,&data[i].BPi,&data[i].ASi,&data[i].BSi);
}

for(i=1;i<=T;i++)
for(j=0;j<=maxP;j++)
res[i][j] = -1000000;

for(i=1;i<=W+1;i++)
for(j=0;j<=data[i].ASi;j++)
res[i][j] = -j*data[i].APi;

for(i=2;i<=T;i++)

{
for(j=0;j<=maxP;j++)
res[i][j] = max(res[i][j],res[i-1][j]);
//由i-w-1天買入,維護在i-w-1天總資產遞增序列
qhead = qtail = 0;
if(i-W-1<1)
continue;
for(j=0;j<=maxP;j++)

{
qe tmp;
tmp.pos = j,tmp.res = res[i-W-1][j] + j*data[i].APi;
queue[qhead++] = tmp;
while(qhead > qtail + 1 && queue[qhead-1].res > queue[qhead-2].res)

{
qhead--;
queue[qhead-1] = tmp;
}
while(qhead > qtail + 1 && data[i].ASi + queue[qtail].pos < j )
qtail++;
res[i][j] = max(res[i][j],res[i-W-1][queue[qtail].pos] - data[i].APi * (j - queue[qtail].pos));
}
qhead = qtail = 0;
for(j=maxP;j>=0;j--)

{
qe tmp;
tmp.pos = j,tmp.res = res[i-W-1][j] + j*data[i].BPi;
queue[qhead++] = tmp;
while(qhead > qtail + 1 && tmp.res > queue[qhead-2].res)

{
qhead--;
}
queue[qhead-1] = tmp;
while(qhead > qtail + 1 && queue[qtail].pos - data[i].BSi > j)
qtail++;
res[i][j] = max(res[i][j],res[i-W-1][queue[qtail].pos] + data[i].BPi * (queue[qtail].pos - j));
}
}
for(i=0;i<=maxP;i++)
if(ans < res[T][i])
ans = res[T][i];
printf("%d\n",ans);
}
return 0;
}
