hdu 3401(单调队列优化dp)
生活随笔
收集整理的這篇文章主要介紹了
hdu 3401(单调队列优化dp)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
注意:這題題意是有操作的天數相隔要大于w
然后列出狀態轉移方程就可以發現,可以用優點隊列優化啦。
構造狀態dp[i][j]表示第i 天擁有 j只股票的時候,賺了多少錢
狀態轉移有:
1、從前一天不買不賣:
dp[i][j]=max(dp[i-1][j],dp[i][j])
2、從前i-W-1天買進一些股:
dp[i][j]=max(dp[i-W-1][k]-(j-k)*AP[i],dp[i][j])
3、從i-W-1天賣掉一些股:
dp[i][j]=max(dp[i-W-1][k]+(k-j)*BP[i],dp[i][j])
?
// // main.cpp // hdu3401 // // Created by New_Life on 16/8/16. // Copyright ? 2016年 chenhuan001. All rights reserved. // #include <iostream> #include <stdio.h> #include <algorithm> #include <queue> #include <string.h> #include <string> using namespace std;#define N 2020 #define INF 100000000/******************_單調隊列模板_******************/ //基于單調隊列功能的單一性:以limit為序查找在一定范圍內的極值。 //復雜度:O(n) //用法: 創建的時候調用.init() // 插入隊列:.push( Q_Node( KEY,LIMIT ) ); // 設置limit值:.setlimit( LIMIT ); // 查詢<limit值的最大元素: Q_Node qn; q2.top(qn); // 再查詢前需要設置limit值,如果隊列為空返回false,否則將最大元素存入qn中并返回truestruct Q_Node {int key,limit;//用來比較大小的key和控制存在時間的limit Q_Node(){}Q_Node(int _key,int _limit){ key=_key,limit=_limit; } };struct Q_Que {Q_Node Q[N];int qf,qd;int limit;// <limit 的元素將被彈出void init() {qf = qd = 0;//將隊列內元素清空 }void push(Q_Node newnode) {//默認入隊是當前limit最大的while (qf>qd && Q[qf-1].key < newnode.key) qf--;Q[qf++] = newnode;}void setlimit(int _limit) {limit = _limit;}/*取出隊列中>=limit且key最大的元素。*/bool top(Q_Node &rt){while(qf>qd && Q[qd].limit < limit) qd++;if(qf==qd) return false;rt = Q[qd];return true;} }q1,q2;int dp[N][N]; int ap[N],bp[N],as[N],bs[N];int main(int argc, const char * argv[]) {int T;cin>>T;while(T--){int t,mxp,w;cin>>t>>mxp>>w;for(int i=1;i<=t;i++) scanf("%d%d%d%d",ap+i,bp+i,as+i,bs+i);for(int i=0;i<=t;i++)for(int j=0;j<=mxp;j++) dp[i][j] = -INF;for(int i=1;i<=w+1;i++)for(int j=0;j<=as[i];j++)dp[i][j] = -j*ap[i];dp[0][0] = 0;for(int i=1;i<=t;i++){q1.init(); q2.init();int sum1=0,sum2=0;for(int j=0;j<=mxp;j++){dp[i][j] = max(dp[i][j],dp[i-1][j]);//啥也沒做 }if(i <= w+1) continue;for(int j=0;j<=mxp;j++){q1.push( Q_Node(dp[i-w-1][j]-sum1,j) );q1.setlimit(j-as[i]);Q_Node qn;if(q1.top(qn)){dp[i][j] = max(dp[i][j],qn.key+sum1);}sum1 -= ap[i];}for(int j=mxp;j>=0;j--){q2.push(Q_Node(dp[i-w-1][j]-sum2, -j));q2.setlimit(-j-bs[i]);Q_Node qn;if(q2.top(qn)) dp[i][j] = max(dp[i][j],qn.key+sum2);sum2 += bp[i];}}int ans = 0;for(int i=1;i<=t;i++)for(int j=0;j<=mxp;j++) ans= max(ans,dp[i][j]);cout<<ans<<endl;}return 0; } /*205 2 02 1 1 12 1 1 13 2 1 14 3 1 15 4 1 15 3 02 1 2 22 1 12 13 2 2 14 3 3 25 4 1 25 2 32 1 3 21 1 12 13 2 2 24 3 3 35 4 1 25 3 32 1 3 21 1 12 13 4 2 21 3 3 31 3 3 55 10 02 1 3 21 1 12 13 4 2 21 3 3 31 3 3 55 10 02 1 3 21 1 12 03 4 4 21 3 0 31 3 0 54 1 11 1 1 11 1 1 11 3 1 11 3 1 1104 3 13 1 1 15 1 1 110 6 1 110 6 1 1*/?
轉載于:https://www.cnblogs.com/chenhuan001/p/5782049.html
總結
以上是生活随笔為你收集整理的hdu 3401(单调队列优化dp)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 折中算法
- 下一篇: 九度oj 题目1537:买卖股票