码迷,mamicode.com
首页 > 其他好文 > 详细

poj1821 Fence

时间:2019-01-02 10:37:39      阅读:143      评论:0      收藏:0      [点我收藏+]

标签:can   inline   style   str   turn   cst   enc   fine   \n   

题目描述

题解:

应该是个$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\n",dp[k][n]);
    }
    return 0;
}

 

poj1821 Fence

标签:can   inline   style   str   turn   cst   enc   fine   \n   

原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10206815.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!