POJ 1821 Fence 单调队列优化DP

来源:互联网 发布:淘宝客服代码 编辑:程序博客网 时间:2024/05/16 08:02

题目大意:有K个工人,长度为N的墙(标号从1-N)。每个工人有三个属性si,li,pi,意味着,工人最多刷长度为li的墙(一定要连续),其中,如果工人要刷墙,必须包含编号si的墙。工人每刷一面墙,可以得到价值pi。如果每面墙最多刷一次,问,能得到最大价值和。


思路:如果按,si排序,dp[ i ][ j ]表示前i个工人,对于前j面墙,取得的最大价值。显然有

dp[i][j] = dp[i-1][j]

       或 = dp[i-1][k] + (j-k)*pi,其中k<si<=j && j-k<=li

看到这种格式,马上想到单调队列优化,但是有点麻烦的是那个限制条件。但是认真分析,k<si<j实际上,单独地和k和j有关,可以很容易处理,j-k<=li则可以利用队列单调性处理。


//#pragma comment(linker, "/STACK:102400000,102400000")#include<cstdio>#include<cstring>#include<vector>#include<queue>#include<cmath>#include<cctype>#include<string>#include<algorithm>#include<iostream>#include<ctime>#include<map>#include<set>using namespace std;#define MP(x,y) make_pair((x),(y))#define PB(x) push_back(x)typedef long long LL;//typedef unsigned __int64 ULL;/* ****************** */const int INF=100011122;const double INFF=1e100;const double eps=1e-8;const LL mod=20120427;const int NN=160010;const int MM=1000010;/* ****************** */int dp[2][NN];int q[NN];struct node{    int p,s,l;    bool operator<(const node &tt)const    {        return s<tt.s;    }}a[105];int main(){    int n,m,t,i,j;    int head,tail,k;    while(scanf("%d%d",&n,&m)!=EOF)    {        for(i=1;i<=m;i++)        {            scanf("%d%d%d",&a[i].l,&a[i].p,&a[i].s);        }        sort(a+1,a+1+m);        memset(dp,0,sizeof(dp));        t=0;        for(i=1;i<=m;i++)        {            t=1-t;            tail=0;            head=1;            q[++tail]=0;            for(j=1;j<=n;j++)            {                dp[t][j]=dp[1-t][j];                while(head<=tail && j>a[i].l+q[head])                    head++;                if(a[i].s<=j && head<=tail)                {                    k=q[head];                    dp[t][j]=max(dp[t][j],dp[1-t][k]+(j-k)*a[i].p);                }                if(j<a[i].s)                {                    while(head<=tail && dp[1-t][j]-j*a[i].p>=dp[1-t][ q[tail] ]-q[tail]*a[i].p)                        tail--;                    q[++tail]=j;                }            }            for(j=1;j<=n;j++)                dp[t][j]=max(dp[t][j],dp[t][j-1]);        }        printf("%d\n",dp[t][n]);    }    return 0;}


0 0