給定一個長度爲n的序列,你能夠進行若干次操做:
選擇一個區間,刪掉,並得到Val[Len]的得分,Len爲這個區間的長度:
其中這個區間知足:
1.相鄰兩個數差的絕對值爲1
2.每一個數都大於相鄰兩個數的平均數
問最大得分。c++
一眼過去,獲得一個多是O(n^4)的作法。
設f[i][j]表示刪除掉[i,j]這個區間的最大得分。
而後發現只有這個轉移不了,而後又多設了一個g[i][j][0/1],表示以a[i]開頭的,以a[j]結尾的上升或降低的最大得分。
而後發現這個好像要多存一個個數,而後很倦生,而後就棄療了。spa
賽後發現,其實標算跟個人作法差很少,多存一維個數能夠用上升序列的性質直接算。
而後打着打着又發現了一個問題。
f[i][j]<-g[i][k]+g[k][j]的合併有點奇怪。
而後水過了以後再看標,恍然大悟。
靠這樣轉移就能夠把兩個g拼接起來了。code
#include<bits/stdc++.h> #define ll long long #define fo(i,x,y) for(int i=x;i<=y;i++) #define fd(i,x,y) for(int i=x;i>=y;i--) using namespace std; const int maxn=407,Inf=0x7fffffff; int n,Val[maxn],a[maxn]; int Up[maxn][maxn],Dn[maxn][maxn]; void getUpDn(){ fo(i,1,n){ Up[i][i]=0; fo(j,i+1,n){ if (Up[i][j-1]) Up[i][j]=Up[i][j-1]; else if (a[j]==a[j-1]+1) Up[i][j]=0; else Up[i][j]=j; } } fo(i,1,n){ Dn[i][i]=0; fo(j,i+1,n){ if (Dn[i][j-1]) Dn[i][j]=Dn[i][j-1]; else if (a[j]==a[j-1]-1) Dn[i][j]=0; else Dn[i][j]=j; } } } void Init(){ scanf("%d",&n); fo(i,1,n) scanf("%d",&Val[i]); fo(i,1,n) scanf("%d",&a[i]); getUpDn(); } int Check(int l,int r,int L=0,int R=0){ if (L){ if (r-l+1==0) return Check(L,R); else if (R-L+1==0) return Check(l,r); else{ int x=Up[l][r]; if (x==0){ if (a[r]+1==a[L]) return Check(L,R); else if (a[r]-1==a[L]) return (Dn[L][R]==0)*2; else return 0; }else{ if (Dn[x-1][r]==0 && a[r]-1==a[L]) return (Dn[L][R]==0)*2; else return 0; } } }else{ if (l==r) return 1; else{ int x=Up[l][r]; if (x==0) return 1; else return (Dn[x-1][r]==0)*2; } } } int f[maxn][maxn],g[maxn],h[maxn][maxn][2],Ans=0; void getF(){ fo(Len,2,n) fo(i,1,n){ int j=i+Len-1; if (j>n) break; fo(k,i,j-1){ if (a[k]+1==a[j]) h[i][j][0]=max(h[i][j][0],h[i][k][0]+f[k+1][j-1]); if (a[k]-1==a[j]) h[i][j][1]=max(h[i][j][1],h[i][k][1]+f[k+1][j-1]); } fo(k,i,j-1){ f[i][j]=max(f[i][j],f[i][k]+f[k+1][j]); } fo(k,i,j-1) if (h[i][k][0]>-1e8 && h[k][j][1]>-1e8) f[i][j]=max(f[i][j],h[i][k][0]+h[k][j][1]+Val[a[k]-a[i]+a[k]-a[j]+1]); if (h[i][j][0]>-1e8) f[i][j]=max(f[i][j],h[i][j][0]+Val[a[j]-a[i]+1]); if (h[i][j][1]>-1e8) f[i][j]=max(f[i][j],h[i][j][1]+Val[a[i]-a[j]+1]); } } void getG(){ g[0]=0; fo(i,1,n){ g[i]=g[i-1]; fo(j,0,i-1){ g[i]=max(g[i],g[j]+f[j+1][i]); } } } void Solve(){ fo(i,1,n) fo(j,1,n) f[i][j]=h[i][j][0]=h[i][j][1]=-1e9; fo(i,1,n){ f[i][i-1]=0; fo(j,i,n){ if (Check(i,j)) f[i][j]=Val[j-i+1]; else f[i][j]=-1e9; if (j>i) h[i][j][0]=h[i][j][1]=-1e9; else h[i][j][0]=h[i][j][1]=0; } } getF(); getG(); Ans=g[n]; } void Print(){ printf("%d\n",Ans); } int main(){ freopen("1.in","r",stdin); freopen("1.out","w",stdout); Init(); Solve(); Print(); return 0; }