Pogo-Cow S
阿新 • • 發佈:2021-06-16
這題出在單調佇列優化dp裡,就離譜好吧......
對不住了上來先噴一波,不過離譜是確實的
dp的含義也很簡單,就是說從j到i的分數最大值
直接上代馬,裡面說的很詳細了
1 #include<bits/stdc++.h> 2 using namespace std; 3 inline int read(){ 4 int x=0,f=1; char ch=getchar(); 5 while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } 6 while(ch>='0'&&ch<='View Code9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); } 7 return x*f; 8 } 9 const int NN=1005; 10 struct SNOW{ 11 int pos,val; 12 }; SNOW a[NN]; 13 int n,wsn,f[NN][NN]; 14 inline bool cmp(SNOW a,SNOW b){return a.pos<b.pos;} 15 namespace WSN{ 16 inline int main(){ 17 n=read();18 for(int i=1;i<=n;i++) a[i].pos=read(),a[i].val=read(); 19 sort(a+1,a+n+1,cmp); 20 for(int j=1;j<=n;j++){//中間過度點 21 int k=j-1,v=f[j][0]+a[j].val;//k是起點,v是起點的初始值 22 for(int i=j+1;i<=n;i++){//終點 23 while(k&&a[i].pos-a[j].pos>=a[j].pos-a[k].pos)//卡一個終點到起點的最值 24 v=max(v,f[j][k]+a[j].val),k--;//比較加入後的權值 25 f[i][j]=max(f[i][j],v); 26 wsn=max(wsn,v+a[i].val);//加上終點的權值 27 } 28 }//因為牛即可以往正方向跑也可以往逆方向跑,所以要遍歷兩遍 29 //因為正反遍歷的時候初始值會從新的開始,那麼他每次更新的點都不會記錄正方向遍歷的值 30 //因此不必用memset 31 for(int j=n;j;j--){ 32 int k=j+1,v=f[j][n+1]+a[j].val; 33 for(int i=j-1;i;i--){ 34 while(k<=n&&a[j].pos-a[i].pos>=a[k].pos-a[j].pos) 35 v=max(v,f[j][k]+a[j].val),k++; 36 f[i][j]=max(f[i][j],v); 37 wsn=max(wsn,v+a[i].val); 38 } 39 }//這就跟上面的一模一樣了 40 printf("%d\n",wsn);//最後直接輸出值 41 return 0; 42 } 43 } 44 signed main(){return WSN::main();}
最後總結一下的話,這個專題並不是在考單調佇列優化dp,而是在考一個優化dp的思想——看單調性!!!
還是要體會整理題目者的良苦用心啊