这道题最开始该考虑的是数组用n+1的大小还是n的大小,因为二叉树的节点是从1开始的,所以用n+1作为数组大小最好。

反复看几遍就懂了:
import java.util.*;
public class Main{
    private static int[][]dp;
    private static int[][]dp2;//存储关于位置的dp
    public static int process(int[]grades){
        int n=grades.length;
        dp=new int[n][n];
        dp2=new int[n][n];
        //叶子结点
        for(int i=1;i<n;i++){
            dp[i][i]=grades[i];
            dp2[i][i]=i;//因为区间节点从0开头,但是实际是从1开头的下标,所以+1
        }
        //非叶子节点
        for(int i=1;i<n;i++){
            for(int j=1;j+i<n;j++){
                    dp[j][i+j]=Integer.MIN_VALUE;
                for(int k=j;k<=i+j;k++){
                    int left=k==j?1:dp[j][k-1];
                    int right=k==j+i?1:dp[k+1][j+i];
                    int score=left*right+grades[k];
                    if(score>dp[j][j+i]){
                        dp[j][j+i]=score;
                        dp2[j][j+i]=k;//因为区间节点从0开头,但是实际是从1开头的下标,所以+1
                    }
                }
            }
        }
        return dp[1][n-1];
    }
    //前序遍历递归
    public static void preOrder(int l,int r){
        if(l>r) return;
        System.out.print(dp2[l][r]+" ");
        preOrder(l,dp2[l][r]-1);
        preOrder(dp2[l][r]+1,r);
    }
    public static void main(String[]args){
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        int[]grades=new int[n+1];
        for(int i=1;i<=n;i++){
            grades[i]=sc.nextInt();
        }
        System.out.println(process(grades));
        preOrder(1,n);
    }
}