poj 1821 单调队列优化dp详解

/* poj 1821
   *******************************************************************
   单调队列优化;
   ******************************************************* 
   dp[i][j]:前i个最终刷到第j块木板所得最大收益;
   dp[i][j]=max(dp[i][j-1],dp[i-1][j]),  dp[i-1][j]:第i个工人不用刷木板;dp[i][j-1]:第j面墙不用刷;
   dp[i][j]=max(dp[i-1][k]+(j-k)*p[i]);  j-l[i]<=k
#include 
#include 
#include 
#include 
#define N 120
#define M 17000
using namespace std;
struct RE
{
    int l,p,s;
}re[N];
int q[M],l[N],r[N],dp[N][17000],n,k;
inline bool cmp(const RE &a,const RE &b)
{
    return a.sh&&dp[i-1][q[t-1]]-q[t-1]*re[i].p<=tmp) t--;
            q[t++]=j;
        }
        for(int j=re[i].s,tmp;j<=r[i];j++)
        {
            while(t>h&&j-q[h]>re[i].l) h++;/*如果i工人最终刷到的位置减去i-1工人最终刷到的位置 比第i个工人
能刷的最大木板长度长,说明根本不可能达到这种状态,从而舍去;*/ 
            dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
            
            dp[i][j]=max(dp[i][j],dp[i-1][q[h]]+(j-q[h])*re[i].p);
        }
        for(int j=r[i]+1;j<=n;j++) dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
    }
    int ans=0;
    for(int i=1;i<=n;i++) ans=max(ans,dp[k][i]);
    printf("%d\n",ans);
}
int main()
{
    while(scanf("%d%d",&n,&k)!=EOF)
    {
        read();
        go();
    }
    return 0;
} 

你可能感兴趣的:(c++)