poj 1821 Fence

来源:互联网 发布:数据库第六版pdf网盘 编辑:程序博客网 时间:2024/06/05 16:38

题目链接:http://poj.org/problem?id=1821

题目思路:单调队列优化,不过要注意界的处理。

#include<stdio.h>#include<stdlib.h>#include<string.h>#include<string>#include<queue>#include<algorithm>#include<vector>#include<stack>#include<list>#include<iostream>#include<map>using namespace std;#define inf 0x3f3f3f3f#define Max 110int max(int a,int b){return a>b?a:b;}int min(int a,int b){return a<b?a:b;}struct node{    int len,p,s;    bool operator<(const node a)const    {        return s<a.s;    }}work[110];int n,k;int len[110],p[110],s[110];int q[16010],l[110],r[110];int dp[110][16010];int main(){    int i,j;    while(scanf("%d%d",&n,&k)!=EOF)    {    for(i=1;i<=k;i++)    {        scanf("%d%d%d",&work[i].len,&work[i].p,&work[i].s);    }    sort(work+1,work+k+1);    for(i=1;i<=k;i++)    {          len[i]=work[i].len;p[i]=work[i].p;s[i]=work[i].s;          l[i]=(s[i]-len[i]+1>=1)?(s[i]-len[i]+1):1;          r[i]=(s[i]+len[i]-1<=n)?(s[i]+len[i]-1):n;    }    for(i=0;i<=n;i++)        dp[0][i]=0;    for(i=1;i<=k+1;i++)    {        for(j=0;j<=n;j++)            dp[i][j]=dp[i-1][j];        //if(i==k+1)         //   continue;        int top=0,tail=0;        q[tail++]=l[i]-1;        for(j=l[i];j<=r[i];j++)        {            while(tail>top&&j-q[top]>len[i])            {                top++;            }            if(j>=s[i])//第i个工人的右界最小为要s[i];            dp[i][j]=max(dp[i][j],dp[i-1][q[top]]+(j-q[top])*p[i]);         //   printf("i %d j %d dp %d q%d\n",i,j,dp[i][j],q[top]);            if(j>=s[i])//前i-1个工人不能做s[i],当要i要做时。                continue;            while(tail>top&&dp[i-1][j]-j*p[i]>=dp[i-1][q[tail-1]]-q[tail-1]*p[i])            {                tail--;            }            q[tail++]=j;        }    }    for(i=n;i>=0;i--)    {        dp[k][n]=max(dp[k][n],dp[k][i]);    }    printf("%d\n",dp[k][n]);    }    return 0;}