zoukankan      html  css  js  c++  java
  • poj1821——Fence

    题意:

    一个栅栏一共有n(从1——n)个木板,我们找k个工人去粉刷它,li表示每个人有限制粉刷木板数量,pi表示粉刷一个木板得到的钱,si表示他开始在那个木板前面

    如果一个工人要粉刷,那么他必须粉刷si这个木板,而且工人粉刷时必须是连续的木板

    题解:

    dp[i][j]表示有i个人粉刷j块木板所获得的最大利润

    dp[i][j]=max(max(dp[i-1][j],dp[i][j-1]),dp[i][k]+(j-k)*p(i))

    dp[i-1][j]表示i-1个人粉刷j块木板所获得的最大利润

    dp[i][j-1]表示i个人粉刷j-1块木板所获得的最大利润

    dp[i][k]+(j-k)*p(i) 这里面的k是枚举在第i个人可以粉刷木板的数量(因为题目要求第i个人必须粉刷si这块木板,那么粉刷区间肯定也包括它)

    //m是一个结构体,里面包含一个工人的li,pi,si
    for(int j = m[i].s;j <= m[i].s + m[i].l - 1;j ++)
            {
                for(int k = j - m[i].l;k <= m[i].s - 1;k ++)
                    if(k >= 0)  
                    {
                        dp[i][j] = max(dp[i][j],dp[i - 1][k] + (j - k) * m[i].p);
                    }
            }

    话可以利用单调队列降低复杂度

    通过上面的代码我们可以看出来j越大,那么k也就随之变大,这就符合单调队列的特性,单调队列(递减队列)里面放dp[i][k]-k*p(i),为什么放这个是因为我们后面枚举j的时候

    直接可以通过   (队列头)+j*p(i) 来找求最优解(这个(j*p(i))与前面的抵消了一部分,剩下的就是第i个人粉刷的部分),因为递减队列头部放的值肯定是最大的,所以

     队列头部就是最好的dp转移位置,为了防止粉刷区间大于l(i),我们要每次先对单调队列中的数据进行处理

    代码:

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<iostream>
     4 #include<algorithm>
     5 #include<queue>
     6 #include<deque>
     7 using namespace std;
     8 typedef long long ll;
     9 const int maxn=2e5+10;  //数组开到2e4都不行,
    10 const int mod = 998244353;
    11 const int INF=0x3f3f3f3f;
    12 struct shudui
    13 {
    14     int l,p,s;
    15 }m[maxn];
    16 bool mmp(shudui x,shudui y)
    17 {
    18     return x.s<y.s;
    19 }
    20 int dp[110][maxn];
    21 struct jihe
    22 {
    23     int k,x;
    24 }str1;
    25 deque<jihe>r;
    26 int main()
    27 {
    28     int n,k;
    29     scanf("%d%d",&k,&n);
    30     for(int i = 1;i <= n;i ++)
    31         scanf("%d%d%d",&m[i].l,&m[i].p,&m[i].s);
    32     sort(m + 1,m + 1 + n,mmp);   //这个要加上
    33 
    34     for(int i=1;i<=n;++i)
    35     {
    36         for(int j = 1;j <= k;j ++)
    37             dp[i][j] = max(dp[i - 1][j],dp[i][j - 1]);
    38 
    39         while(r.size()) r.pop_back();
    40         for(int kk = max(m[i].s - m[i].l,0);kk <= m[i].s - 1;kk ++)
    41         {
    42             int tmp = dp[i - 1][kk] - kk * m[i].p;
    43 
    44             while(r.size() && r.back().x < tmp) r.pop_back();
    45             str1.k=kk;
    46             str1.x=tmp;
    47             r.push_back(str1);
    48         }
    49         for(int j = m[i].s;j <= m[i].s + m[i].l - 1;j ++)
    50         {
    51             while(r.size() && r.front().k < j - m[i].l) r.pop_front();
    52             dp[i][j] = max(dp[i][j],r.front().x + j * m[i].p);
    53         }
    54     }
    55     int ans = 0;
    56     for(int i = 1;i <= k;i ++)
    57         ans = max(ans,dp[n][i]);
    58     printf("%d
    ",ans);
    59     return 0;
    60 }
    View Code
  • 相关阅读:
    [NOI2009]管道取珠
    Rebalance再均衡
    生产者分区写入策略
    Kafka事务
    幂等性
    消费者组
    Kafka中的重要概念
    偏移量offset
    服务注册和发现的意思,Spring cloud如何实现?
    负载平衡的意义
  • 原文地址:https://www.cnblogs.com/kongbursi-2292702937/p/11310800.html
Copyright © 2011-2022 走看看