您的位置:首页 > 其它

hdu 3401 Trade 单调队列优化dp

2012-08-27 09:59 507 查看
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
[i]);
}
printf("%d\n", mm);
}
return 0;
}




























                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: