[HDU3401]Trade && 单调队列优化DP

来源:互联网 发布:极点五笔 centos 编辑:程序博客网 时间:2024/05/02 01:58

从前W+1天前转移过来 用单调队列来存i-W-1(下称Last)天的最大收益 进行买入卖出的选择

#include<cstdio>#include<cstring>#include<deque>#include<queue>#include<algorithm>#define MAXN 2000#define MAXK 3000int INF;using namespace std;typedef long long LL;typedef pair<int, int> pii;int dp[MAXN+10][MAXK+10];int MIN[MAXN+10], MON[MAXN+10], NIN[MAXN+10], NON[MAXN+10];deque <pii> q;int main(){int kase;scanf("%d", &kase);while(kase--){int Day, MAX, W;q.clear(); memset(dp, 11111111, sizeof(dp));INF = dp[0][0];scanf("%d%d%d", &Day, &MAX, &W);for(int i = 1; i <= Day; i++) scanf("%d%d%d%d", &MIN[i], &MON[i], &NIN[i], &NON[i]);for(int d = 1; d <= W+1; d++)for(int j = 0; j <= NIN[d]; j++){dp[d][j] = 0;dp[d][j] -= j * MIN[d];}for(int i = 2; i <= Day; i++){for(int j = 0; j <= MAX; j++) dp[i][j] = max(dp[i][j], dp[i-1][j]);if(i <= W+1) continue;q.clear();int Last = i-W-1;pii tmp;for(int j = 0; j <= MAX; j++){tmp.first = j;tmp.second = dp[Last][j] + MIN[i]*j;while(!q.empty() && q.back().second < tmp.second) q.pop_back();q.push_back(tmp);if(q.front().first + NIN[i] < j) q.pop_front();dp[i][j] = max(dp[i][j], q.front().second - MIN[i]*j);}q.clear();for(int j = MAX; j >= 0; j--){tmp.first = j;tmp.second = dp[Last][j] + MON[i]*j;while(!q.empty() && q.back().second < tmp.second) q.pop_back();q.push_back(tmp);if(q.front().first - NON[i] > j) q.pop_front();dp[i][j] = max(dp[i][j], q.front().second - MON[i]*j);}}printf("%d\n", dp[Day][0]);}}

0 0
原创粉丝点击