Loading

Pogo-Cow S

这题出在单调队列优化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<='9'){ 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();}
View Code

最后总结一下的话,这个专题并不是在考单调队列优化dp,而是在考一个优化dp的思想——看单调性!!!

还是要体会整理题目者的良苦用心啊

posted @ 2021-06-16 19:07  雪域亡魂  阅读(103)  评论(0)    收藏  举报