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的主要内容,如果未能解决你的问题,请参考以下文章