题解 P1430【序列取数】

· · 题解

Part 1

代码1:

#include<cstdio>
const int N=1002;
int  T,n,i,j,len,a[N],s[N],l[N][N],r[N][N];
int max(int x,int y){
    return x>y?x:y;
}
int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        for(i=1;i<=n;i++){
            scanf("%d",a+i);
            s[i]=s[i-1]+a[i];
            l[i][i]=r[i][i]=a[i];
        }
        for(len=1;len<n;len++)
            for(i=1;i+len<=n;i++){
                j=i+len;
                l[i][j]=a[i]+max(l[i+1][j],s[j]-s[i]-max(l[i+1][j],r[i+1][j]));
                r[i][j]=a[j]+max(r[i][j-1],s[j-1]-s[i-1]-max(l[i][j-1],r[i][j-1]));
            }
        printf("%d\n",max(l[1][n],r[1][n]));
    }
}

Part 2

这时候代码可能长这样:

#include<cstdio>
const int N=1002;
int  T,n,i,j,len,a[N],s[N],l[N][N],r[N][N];
int max(int x,int y){
    return x>y?x:y;
}
int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        for(i=1;i<=n;i++){
            scanf("%d",a+i);
            s[i]=s[i-1]+a[i];
            l[i][0]=r[i][0]=a[i];
        }
        for(j=1;j<n;j++)
            for(i=1;i+j<=n;i++){
                l[i][j]=a[i]+max(l[i+1][j-1],s[i+j]-s[i]-max(l[i+1][j-1],r[i+1][j-1]));
                r[i][j]=a[i+j]+max(r[i][j-1],s[i+j-1]-s[i-1]-max(l[i][j-1],r[i][j-1]));
            }
        printf("%d\n",max(l[1][n-1],r[1][n-1]));
    }
}

然后我们就可以把j这一维去掉了:

#include<cstdio>
const int N=1002;
int T,n,i,j,a[N],s[N],l[N],r[N];
int max(int x,int y){
    return x>y?x:y;
}
int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        for(i=1;i<=n;i++){
            scanf("%d",a+i);
            s[i]=s[i-1]+a[i];
            l[i]=r[i]=a[i];
        }
        for(j=1;j<n;j++)
            for(i=1;i+j<=n;i++){
                r[i]=a[i+j]+max(r[i],s[i+j-1]-s[i-1]-max(l[i],r[i]));
                l[i]=a[i]+max(l[i+1],s[i+j]-s[i]-max(l[i+1],r[i+1]));
                //注意要先转移r[i],再转移l[i],因为r[i]的转移需要l[i]前一维的值
            }
        printf("%d\n",max(l[1],r[1]));
    }
}