• POJ 1821 Fence(单调队列优化DP)


    大意:
    有 N 块连续的木板,并有 K 个工人来粉刷,但不要求全部粉刷。每个工人有三个参数:L,P,S,表示其最多粉刷连续的 L 块木板,并且每粉刷一块木板可获得 P 元,但所粉刷的木板必须包括第 S 块。输出所能获得最大价值。
    思路:
    dp[i][j] 表示第 i 个人粉刷到第 j 块木板,所获得最大价值。
    dp[i][j] = max{ dp[i][j-1] , dp[i-1][j] , dp[i-1][k] + (j-k)·p[i] }
    分别表示:第 i 个人不刷、第 j 面墙不刷、第 i 个人刷 k+1 到 j 块木板。且对于第三种,需满足 j-l[i]<=k<=s[i]-1 和 s[i]<=j<=s[i]+l[i]-1。
    对于第三项来说,需要进行优化,可以发现转化为 dp[i-1][k]+k×p[i] 和 j×P[i] 这两项,后一项是常数,那么只需要单调队列求出前面的最大值即可

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    const int MAXM = 200;
    const int MAXN = 2e5 + 5;
    typedef long long LL;
    
    struct node {
        int l, p, s;
    } a[MAXM];
    int n, m, le[MAXM], re[MAXM], q[MAXM], dp[MAXM][MAXN];
    bool cmp(const node &a, const node &b) { return a.s < b.s; }
    int main() {
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= m; i++) scanf("%d%d%d", &a[i].l, &a[i].p, &a[i].s);
        sort(a + 1, a + m + 1, cmp);
        for (int i = 1; i <= m; i++) {
            le[i] = max(0, a[i].s - a[i].l);      
            re[i] = min(n, a[i].s + a[i].l - 1);  
        }
        for (int i = 1; i <= m; i++) {
            int l = a[i].l;
            int p = a[i].p;
            int s = a[i].s;
            for (int j = 0; j <= re[i]; j++)
                dp[i][j] = dp[i - 1][j]; 
            int h = 1;
            int t = 0;
            for (int j = le[i]; j < a[i].s; j++) {  //维护单调队列
                while (h <= t && dp[i - 1][j] - j * p >= dp[i - 1][q[t]] - q[t] * p)
                    t--;
                q[++t] = j;
            }
            for (int j = s; j <= re[i]; j++) {
                while (h < t && j - q[h] > l) h++;  
                dp[i][j] = max(dp[i][j - 1], dp[i - 1][j]);
                dp[i][j] = max(dp[i][j], dp[i - 1][q[h]] + (j - q[h]) * p);
            }
            for (int j = re[i] + 1; j <= n; j++)
                dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
        }
        int ans = 0;
        for (int i = 1; i <= n; i++) ans = max(ans, dp[m][i]);
        printf("%d
    ", ans);
        return 0;
    }
    
  • 相关阅读:
    JAVA日常之三
    java将字符串存入oracle的Blob中
    java连接oracle数据库
    JAVA日常之二
    JAVA日常之一
    linux日常命令之三
    linux日常命令之二
    linux日常命令之一
    Python之路【第四十篇】:django日更
    Python之路【第三十九篇】:django日更
  • 原文地址:https://www.cnblogs.com/dyhaohaoxuexi/p/14535155.html
Copyright © 2020-2023  润新知