MS(dp , 0);//清零
    for(int len=2; len<=n; len++){ //枚举长度
        for(int i=0; i<n; i++){//枚举起点
            int j = i + len - 1;//计算终点
            if(j >= n) break;//不可越界
            if(conditon) state transition...//根据条件写状态转移方程
            for(int k=i; k<j; k++){ //枚举中间点,合并
                dp[i][j] = max(dp[i][j] , dp[i][k] + dp[k+1][j] + cost)
            }
        }
    }
int dp[maxn][maxn];
string s;
int n;
void solve(){
    rep(len , 2 , n){
        rep(i , 0, n - 1){
            int j=i+len-1;
            if(j >= n) break;
            //cout<<s[i]<<": "<<s[j]<<endl;
            if(s[i] == '(' &&  s[j] == ')' ||  s[i] == '[' &&  s[j] == ']') dp[i][j] = dp[i+1][j-1] + 2;
            rep(k, i, j-1){
                dp[i][j] = max(dp[i][j] , dp[i][k] + dp[k+1][j]);
            }
        }
    }
}
int main(){
    while(cin>>s){
       
        if(s == "end") break;
        n = s.length();
        MS(dp , 0);
        solve();
        cout<<dp[0][n-1]<<endl;
    }
    return 0;
}
ll a[maxn];
ll dp[maxn][maxn];
void solve(){
    rep(len , 3 , n){ //枚举区间长度,长度至少是3
        rep(i, 1, n){ //枚举起点
            int j=i+len-1; //得到终点
            if(j > n) break; //检查越界
            dp[i][j] = inf; //求最小值 先初始化inf
            rep(k, i+1, j-1){ //枚举中间点
                dp[i][j] = min(dp[i][j] , dp[i][k] +  dp[k][j] + a[i]*a[k]*a[j]);
            }
        }
    }
}
int main(){
    while(sc(n) != EOF){
        rep(i,1,n) scl(a[i]); //从1开始读数字
        MS(dp,0);//初始化DP
        solve();
        cout<<dp[1][n]<<endl;
    }
    return 0;
}
原文:https://www.cnblogs.com/czsharecode/p/12308148.html