hdu 3401 Trade 單調隊列優化dp

hdu 3401 Trade

http://acm.hdu.edu.cn/showproblem.php?pid=3401

題意:已知未來n天股市的形式、最多可持股量maxp、最少隔w天可操作,以及每天買進價格bp、賣出價格sp、最多可買進數量bn、最多可賣出數量sn

求最大收益

/*
    dp[i][j]= MAX(dp[i][j], dp[i-1][j]); //不動
    dp[i][j]= MAX(dp[i][j], MAX(dp[i-w-1][k] + k*sp[i]) - j*sp[i]); //賣
    // 0<= (k-j)<= sn[i]
    dp[i][j]= MAX(dp[i][j], MAX(dp[i-w-1][k] + k*bp[i]) - j*bp[i]); //買
    // 0<= (j-k)<= bn[i]
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn= 2010;
int bp[maxn], sp[maxn], sn[maxn], bn[maxn], maxp, w, n, dp[maxn][maxn];
struct node{
    int pos, val;
}que[maxn];
int MAX(int x, int y){
    return x>y?x:y;
}
int MIN(int x, int y){
    return x<y?x:y;
}
void dynamic(){
    int i, j, k, head, tail, s, pre;
    node tmp;
    memset( dp, 0xcf, sizeof( dp));
    for( i=1; i<= n; i++){
        for( j= 0; j<=MIN(maxp, bn[i]); j++){
            dp[i][j]= -bp[i]*j;
        }
    }
    for( i= 2; i<= n; i++){
        for( j= 0; j<=maxp; j++){
            dp[i][j]= MAX(dp[i][j], dp[i-1][j]);
        }
    }
    for( i= w+2; i<=n; i++){
       // k= 0;                         //buy
        pre= i- w - 1;
        head=0; tail= -1;
	/*
        對於買的情況
        dp[i][j]= MAX(dp[i][j], MAX(dp[i-w-1][k] + k*bp[i]) - j*bp[i]);    
        0<= (j-k)<= bn[i]
        pre天的股票數<= i天的數量,故k只需枚舉到最大i天目前所看的最大數量,即j 故處理買的情況j應從0~maxp更新,用單調隊列維護 
        */ 
        for( j= 0; j<= maxp; j++){
            dp[i][j]= MAX(dp[i][j], dp[i-1][j]);
            tmp.val= dp[pre][j] + j*bp[i];
            tmp.pos= j;
            while( head <= tail && que[tail].val < tmp.val) tail--;
            que[++tail]= tmp;
            while( head <= tail && (j- que[head].pos ) > bn[i]) head++;
            if( head <= tail) dp[i][j]= MAX( dp[i][j], que[head].val - j*bp[i] );
           // cout<<"a"<<i<<"  "<<j<<"  "<<dp[i][j]<<endl;
        }
        head= 0; tail= -1;       //sell
        for( j= maxp; j>= 0; j--){
            dp[i][j]= MAX(dp[i][j], dp[i-1][j]);
            tmp.val= dp[pre][j] + j*sp[i];
            tmp.pos= j;
            while( head <= tail && que[tail].val < tmp.val) tail--;
            que[++tail]= tmp;
            while( head <= tail && ( que[head].pos - j) > sn[i]) head++;
            if( head <= tail) dp[i][j]= MAX( dp[i][j], que[head].val - j*sp[i]);
           // cout<<i<<"  "<<j<<"  "<<dp[i][j]<<endl;
        }
    }
}
int main(){
  //  freopen("1.txt", "r", stdin);
    int i, j, k, T, mm;
    scanf("%d", &T);
    while( T--){
        scanf("%d%d%d", &n, &maxp, &w);
        for( i=1; i<=n; i++){
            scanf("%d%d%d%d", &bp[i], &sp[i], &bn[i], &sn[i]);
        }
        dynamic();
        mm= 0;
        for( i=0 ; i<=maxp; i++ ){
            mm= MAX(mm, dp[n][i]);
        }
        printf("%d\n", mm);
    }
    return 0;
}




























發佈了69 篇原創文章 · 獲贊 1 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章