【POJ1821】Fence
生活随笔
收集整理的這篇文章主要介紹了
【POJ1821】Fence
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
單調隊列優化dp
我們將每個人的s值排序,這樣我們就能保證當前這個人刷的木板一定在上一個人之后,我們就能進行線型dp
定義f[i][j]表示前i個人刷前j個木板獲得的最多報仇,那么有
在dp過程中,我們假定外層變量i為定值,當j增大時,不難發現k的取值范圍上界不變,下界變大。我們不妨比較一下兩個決策k1,k2,假設k1<k2≤Si-1
因為k2的位置靠后,所以k1最更早的被排除,如果此時滿足
說明k2不僅更優,而且它存活的時間更長,我們就可以將k1排除。
因此,我們可以建立一個單調隊列,存儲決策允許集合并且保證決策點k單調遞增,數值f[i-1][k]-Pi*k單調遞減的序列。每次我們取出隊頭決策(最優)進行轉移即可。
所以,我們就可以設計dp解決問題了
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 typedef long long ll; 7 inline int read() { 8 int ret=0; 9 int op=1; 10 char c=getchar(); 11 while(c<'0'||c>'9') {if(c=='-') op=-1; c=getchar();} 12 while(c<='9'&&c>='0') ret=ret*10+c-'0',c=getchar(); 13 return ret*op; 14 } 15 struct node { 16 int l,s,p; 17 bool operator <(const node &x) const { 18 return s<x.s; 19 } 20 }a[110]; 21 int n,m,f[110][16010]; 22 int q[16010],l,r; 23 inline int calc(int i,int k) { 24 return f[i-1][k]-a[i].p*k; 25 } 26 int main() { 27 n=read(); m=read(); 28 for(int i=1;i<=m;i++) { 29 a[i].l=read(); 30 a[i].p=read(); 31 a[i].s=read(); 32 } 33 sort(a+1,a+m+1); 34 for(int i=1;i<=m;i++) { 35 l=1,r=0; 36 for(int k=max(0,a[i].s-a[i].l);k<=a[i].s-1;k++) { 37 while(l<=r&&calc(i,k)>=calc(i,q[r])) r--; 38 q[++r]=k; 39 } 40 for(int j=1;j<=n;j++) { 41 f[i][j]=max(f[i-1][j],f[i][j-1]); 42 if(j>=a[i].s) { 43 while(l<=r&&j-a[i].l>q[l]) l++; 44 if(l<=r) f[i][j]=max(f[i][j],calc(i,q[l])+j*a[i].p); 45 } 46 } 47 } 48 printf("%d\n",f[m][n]); 49 return 0; 50 } AC Code?
轉載于:https://www.cnblogs.com/shl-blog/p/10989144.html
總結
以上是生活随笔為你收集整理的【POJ1821】Fence的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: H2内嵌数据库的使用
- 下一篇: 面筋和底筋有什么区别?