LuoguP3089 [USACO13NOV]POGO的牛Pogo-Cow
题目链接戳这里
简明题意
第二步:我们观察式子:
我们发现和原来的式子非常像,好像可以直接
因为这个时候我们是从
for(int j=1;j<=N;j++){
f[j][j]=s(j);//边界
for(int i=j+1,now=j+1;i<=N;i++){
f[i][j]=f[i-1][j]-s(i-1);//先得到之前的max
while(now>1 && x(j)-x(now-1)<=x(i)-x(j))
f[i][j]=max(f[i][j],f[j][--now]);//取拓展到k的最大值
f[i][j]+=s(i);//直接转移
Ans=max(Ans,f[i][j]);
}
}
如果是一直往左跳,就反着做一遍 DP 就可以了。
由于每个
程序
#include <cstdio>
#include <algorithm>
using namespace std;
int read(){
char ch=getchar();int f=1,num=0;
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while('0'<=ch&&ch<='9'){num=num*10+ch-'0';ch=getchar();}
return num*f;
}
int N,f[1002][1002],Ans;
struct Point{int x,s;} point[1002];
bool cmp(Point a,Point b){return a.x<b.x;}
#define x(i) point[i].x
#define s(i) point[i].s
int main(){
N=read();
for(int i=1;i<=N;i++)x(i)=read(),s(i)=read();
sort(point+1,point+1+N,cmp);
for(int j=1;j<=N;j++){
f[j][j]=s(j);//边界
for(int i=j+1,now=j+1;i<=N;i++){
f[i][j]=f[i-1][j]-s(i-1);//先得到之前的max
while(now>1 && x(j)-x(now-1)<=x(i)-x(j))
f[i][j]=max(f[i][j],f[j][--now]);//取拓展到k的最大值
f[i][j]+=s(i);//直接转移
Ans=max(Ans,f[i][j]);
}
}
for(int j=N;j>=1;j--){
f[j][j]=s(j);
for(int i=j-1,now=j-1;i>=1;i--){
f[i][j]=f[i+1][j]-s(i+1);
while(now<N && x(now+1)-x(j)<=x(j)-x(i))
f[i][j]=max(f[i][j],f[j][++now]);
f[i][j]+=s(i);
Ans=max(Ans,f[i][j]);
}
}
printf("%d",Ans);
return 0;
}