P3089 [USACO13NOV] Pogo-Cow S
/* 目标点i在目标点x(i),该点得分为p(i) 开始时可以选择站在一个目标点上,只允许朝一个方向跳跃,从一目标点跳到另外一个目标点,每次跳跃的距离至少和上一次跳跃的距离相等,并且必须跳到一个目标点。 每跳到一个目标点,贝西可以拿到该点的得分,请计算他的最大可能得分 f[i][dis]:当前点是i 上一次跳了dis f[i][dis]=max(f[j][k]+p[i]) p[i]-p[j]==dis>k ->O[nk] TLE f[i][j]:point i->point j max score f[i][j]=max[f[k][j]+p[i]] x[j]-x[k]<=x[i]-x[j] f[i][i]=p[i] ->O[n^3] TLE 但是f[i][j] i->j存储的 先循环j i 在读取fij缓存 时数据连续 n^3/10 f[i][j]=max[f[k][j]]+p[i] k j i x(j)−x(k)≤x(i)−x(j) (k<=j,j<=i) f[i-1][j]=max[f[k][j]]+p[i-1] (k<=j,j<=i-1) f[i][j]=f[i-1][j]-p[i-1]+p[i] x(j)−x(k)≤x(i−1)−x(j) 所以k的范围变大 最大值更大了 */ /* 6 5 6 1 1 10 5 7 6 4 8 8 10 25 */ #include<cstdio> #include<iostream> #include<algorithm> #include<cmath> #include<string.h> #include<queue> #include<vector> #include<bits/stdc++.h> typedef long long ll; #define ddd printf("-----------------------\n"); using namespace std; const int maxn=1e1 +10; const int mod=998244353; const int inf=0x3f3f3f3f; int read() { int res=0,f=1;char ch=getchar(); while(isdigit(ch)==0){ if(ch=='-') f=-1; ch=getchar();} while(isdigit(ch)){ res=res*10+ch-'0'; ch=getchar();} return f*res; } int n,f[2010][2010],ans; struct node{ int x,p; bool operator<(const node &b)const{ return x<b.x; } }a[2010]; int main() { ios::sync_with_stdio(false); // cin>>n; n=read();//cout<<n<<endl; for(int i=1;i<=n;i++) a[i].x=read(),a[i].p=read(); sort(a+1,a+1+n); for(int j=1;j<=n;j++)//k j i { for(int i=j+1;i<=n;i++) { f[j][j]=a[j].p; int tmp=a[j].p;//可能不存在 for(int k=j-1;k>=1;k--) { if(a[i].x-a[j].x>=a[j].x-a[k].x) tmp=max(tmp,f[j][k]); } f[i][j]=tmp+a[i].p; ans=max(ans,f[i][j]); } } memset(f,0,sizeof(f)); for(int j=n;j>=1;j--)//i j k { for(int i=j-1;i>=1;i--) { f[j][j]=a[j].p; int tmp=a[j].p; for(int k=j+1;k<=n;k++) { if(-a[i].x+a[j].x>=-a[j].x+a[k].x) tmp=max(tmp,f[j][k]); } f[i][j]=tmp+a[i].p; ans=max(ans,f[i][j]); } } cout<<ans<<'\n'; return 0; }