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();}
最后总结一下的话,这个专题并不是在考单调队列优化dp,而是在考一个优化dp的思想——看单调性!!!
还是要体会整理题目者的良苦用心啊

浙公网安备 33010602011771号