bzoj 1855 dp + 单调队列优化

Posted cjlhy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 1855 dp + 单调队列优化相关的知识,希望对你有一定的参考价值。

思路:很容易写出dp方程,很容易看出能用单调队列优化。。

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define PII pair<int, int>
#define y1 skldjfskldjg
#define y2 skldfjsklejg

using namespace std;

const int N = 2000 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 10000;

int n, m, w, ap[N], bp[N], as[N], bs[N], dp[N][N];
int stk[N], head, rear;

int cal1(int p, int i, int x) {
    return dp[p][x] + x * ap[i];
}

int cal2(int p, int i, int x) {
    return dp[p][x] + x * bp[i];
}

int main() {
    scanf("%d%d%d", &n, &m, &w);
    for(int i = 1; i <= n; i++)
        scanf("%d%d%d%d", &ap[i], &bp[i], &as[i], &bs[i]);

    for(int i = 0; i <= n; i++)
        for(int j = 0; j <= m; j++)
            dp[i][j] = -inf;
    dp[0][0] = 0;

    int ans = 0;
    for(int i = 1; i <= n; i++) {
        head = 1, rear = 0;
        int p = max(0, i - w - 1);

        for(int j = 0; j <= m; j++) dp[i][j] = dp[i - 1][j];
        for(int j = 0; j <= m; j++) {
            while(rear >= head && cal1(p, i, j) > cal1(p, i, stk[rear])) rear--;
            stk[++rear] = j;
            while(j - as[i] > stk[head]) head++;
            dp[i][j] = max(dp[i][j], cal1(p, i, stk[head]) - j * ap[i]);
        }

        head = 1, rear = 0;
        for(int j = m; j >= 0; j--) {
            while(rear >= head && cal2(p, i, j) > cal2(p, i, stk[rear])) rear--;
            stk[++rear] = j;
            while(j + bs[i] < stk[head]) head++;
            dp[i][j] = max(dp[i][j], cal2(p, i, stk[head]) - j * bp[i]);
            ans = max(ans, dp[i][j]);
        }
    }

    printf("%d
", ans);
    return 0;
}

/*
*/

 

以上是关于bzoj 1855 dp + 单调队列优化的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ1855 [Scoi2010]股票交易 单调队列优化dp

笔记篇单调队列优化dp学习笔记&&luogu2569_bzoj1855股票交♂易

BZOJ1855[Scoi2010]股票交易 DP+单调队列

[bzoj1855][Scoi2010]股票交易_动态规划_单调队列

bzoj1855 [Scoi2010]股票交易

1855: [Scoi2010]股票交易[单调队列优化DP]