1. 程式人生 > >[bzoj1855][Scoi2010]股票交易

[bzoj1855][Scoi2010]股票交易

void 股票行情 在那 交易所 inpu desc 整數 for logs

Description

最近lxhgww又迷上了投資股票,通過一段時間的觀察和學習,他總結出了股票行情的一些規律。 通過一段時間的觀察,lxhgww預測到了未來T天內某只股票的走勢,第i天的股票買入價為每股APi,第i天的股票賣出價為每股BPi(數據保證對於每個i,都有APi>=BPi),但是每天不能無限制地交易,於是股票交易所規定第i天的一次買入至多只能購買ASi股,一次賣出至多只能賣出BSi股。 另外,股票交易所還制定了兩個規定。為了避免大家瘋狂交易,股票交易所規定在兩次交易(某一天的買入或者賣出均算是一次交易)之間,至少要間隔W天,也就是說如果在第i天發生了交易,那麽從第i+1天到第i+W天,均不能發生交易。同時,為了避免壟斷,股票交易所還規定在任何時間,一個人的手裏的股票數不能超過MaxP。 在第1天之前,lxhgww手裏有一大筆錢(可以認為錢的數目無限),但是沒有任何股票,當然,T天以後,lxhgww想要賺到最多的錢,聰明的程序員們,你們能幫助他嗎?

Input

輸入數據第一行包括3個整數,分別是T,MaxP,W。 接下來T行,第i行代表第i-1天的股票走勢,每行4個整數,分別表示APi,BPi,ASi,BSi。

Output

輸出數據為一行,包括1個數字,表示lxhgww能賺到的最多的錢數。

Sample Input

5 2 0
2 1 1 1
2 1 1 1
3 2 1 1
4 3 1 1
5 4 1 1

Sample Output

3

HINT

對於30%的數據,0 < =W 對於50%的數據,0 < =W 對於100%的數據,0 < =W
對於所有的數據,1 < =BPi < =APi < =1000,1 < =ASi,BSi < =MaxP

題解:

DP(狀態一大堆的那種毒瘤DP) ps:i表示第i天,j表示買j股股票 四種情況: 第一種,直接買 f[i][j]=-1*j*ap(理解成初始化?) 第二種,什麽都不做,f[i][j]=max(f[i-1][j],f[i][j]) 第三種,在之前基礎上買 分析一下,因為題目中說每次購買股票需要間隔w天,也就是說如果你第i天買了股票,那麽上一次購買一定是在第i-w-1天,設在那之前手上一共有k張股票,於是可以得出方程:f[i][j]=max(f[i][j],f[i-w-1][(j-k)*ap]) 第四種,賣出股票,與第三種類似,一樣設在這之前手中一共有k張股票,只需修改一下,就可以得到方程:
f[i][j]=max(f[i][j],f[i-w-1][k+(k-j)*bp]) 於是就這麽愉快的TLE了 顯然,n^3的復雜度是會被毒瘤出題人卡掉的,要不然怎麽對得起省選名號? 再看一下需要n^3復雜度的情況3和4,想想如何優化 方程:f[i][j]=max(f[i][j],f[i-w-1][(j-k)*ap]) 由前面的分析可以知道,j,k,as滿足下面的關系: j-as<=k<=j f[i][j]=max(f[i][j],f[i-w-1][k+k*ap])-j*ap 再轉化一下,其實就是在j-as到j這個區間內,找出最大值,發現了什麽?就是滑動窗口求最大值這種模板類的東西(放入隊列的元素即f[i-w-1][k+k*ap]) 所以成功祭出單調隊列大法,化掉k這一層循環 方程:f[i][j]=max(f[i][j],f[i-w-1][k+k*ap]-j*ap) 同理可將第四種情況化為f[i][j]=max(f[i][j],f[i-w-1][k+k*bp]-j*bp) 其實三四種情況基本一樣,還有就是第四種情況需要倒序枚舉 代碼:
#include <cstdio>
#include <cstring>
#define ll int
#define inf 1<<30
#define mt(x,y) memset(x,y,sizeof(x))
#define max(x,y) x>y?x:y
#define min(x,y) x<y?x:y
#define abs(x) x>0?x:-x
inline void read(ll &x){
    x=0;ll f=1;char c=getchar();
    while(c<0||c>9){if(c==-)f=-f;c=getchar();}
    while(c>=0&&c<=9){x=x*10+c-0;c=getchar();}
    x*=f;
}
using namespace std;
#define N 2010
ll f[N][N],q[N];
ll t,mp,w,ap,as,bp,bs,ans=0,l,r;
int main(){
    memset(f,128,sizeof(f));
    read(t);read(mp);read(w);
    for(ll i=1;i<=t;i++){
        read(ap);read(bp);read(as);read(bs);
        for(ll j=0;j<=as;j++)f[i][j]=-1*j*ap;
        for(ll j=0;j<=mp;j++)f[i][j]=max(f[i][j],f[i-1][j]);
        if(i<=w)continue;
        l=1,r=0;
        for(ll j=0;j<=mp;j++){
            while(l<=r&&q[l]<j-as)l++;
            while(l<=r&&f[i-w-1][q[r]]+q[r]*ap<=f[i-w-1][j]+j*ap)r--;
            q[++r]=j;
            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;
        for(ll j=mp;j>=0;j--){
            while(l<=r&&q[l]>j+bs)l++;
            while(l<=r&&f[i-w-1][q[r]]+q[r]*bp<=f[i-w-1][j]+j*bp)r--;
            q[++r]=j;
            if(l<=r)f[i][j]=max(f[i][j],f[i-w-1][q[l]]+q[l]*bp-j*bp);
        }
    }
    for(ll i=0;i<=mp;i++){
        ans=max(ans,f[t][i]);
    }
    printf("%d\n",ans);
    return 0;
}

轉載請註明出處:http://www.cnblogs.com/henry-1202/p/8733347.html

[bzoj1855][Scoi2010]股票交易