poj1821 Fence

Posted liguanlin1124

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了poj1821 Fence相关的知识,希望对你有一定的参考价值。

题目描述

题解:

应该是个$dp$;

$dp[i][j]$表示第$i$个人涂到第$j$块的最大收益。

推一下式子:$$dp[i][j]=max(dp[i-1][j],dp[i][j-1],dp[i-1][k]+(j-k)*p[i])$$

对于最后面那个式子可以化一下:$$max(dp[i-1][k]+(j-k)*p[i])=max(dp[i-1][k]-k*p[i])+j*p[i]$$

然后发现这是个单调队列优化dp。

搞一下$k$的范围就结束了。

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 16050
#define K 105
#define ll long long
inline int rd()
{
    int f=1,c=0;char ch=getchar();
    while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar();}
    while(ch>=0&&ch<=9){c=10*c+ch-0;ch=getchar();}
    return f*c;
}
int n,k;
struct edc
{
    int l,p,s;
}o[K];
bool cmp(edc a,edc b){return a.s<b.s;}
ll dp[K][N];
int sta[N],hd,tl;
int main()
{
    while(scanf("%d%d",&n,&k)>0)
    {
    for(int i=1;i<=k;i++)
        o[i].l=rd(),o[i].p=rd(),o[i].s=rd();
    sort(o+1,o+1+k,cmp);
    for(int i=1;i<=k;i++)
    {
        hd=1,tl=1;
        sta[1]=0;
        for(int j=1;j<=n;j++)
        {
            dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
            while(hd<=tl&&sta[hd]<j-o[i].l)hd++;
            if(hd<=tl&&j>=o[i].s)dp[i][j]=max(dp[i][j],dp[i-1][sta[hd]]+1ll*(j-sta[hd])*o[i].p);
            if(j<o[i].s)
            {
                while(hd<=tl&&(dp[i-1][sta[tl]]-sta[tl]*o[i].p)<(dp[i-1][j]-j*o[i].p))tl--;
                sta[++tl]=j;
            }
        }
    }
    printf("%lld
",dp[k][n]);
    }
    return 0;
}

 

以上是关于poj1821 Fence的主要内容,如果未能解决你的问题,请参考以下文章

poj1821 Fence

POJ1821 Fence 单调队列优化DP

POJ1821Fence

ybtoj 单调队列课堂过关 例题2POJ 1821DP粉刷木板 & Fence

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

poj 3253 Fence Repair 贪心