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;
}