最小中间和

题目描述

给定一个正整数序列a1,a2,...,an,不改变序列中的每个元素在序列中的位置,把它们相加,并用括号记每次加法所得的和,称为中间和。
编程:找到一种方法,添上n-1对括号,加法运算依括号顺序进行,得到n-2个中间和,使得求出使中间和最少。
例如给出的序列是4,1,2,3。
第一种添加括号方法:
  ((4+1)+(2+3))=((5)+(5))=(10),有三个中间和是5,5,10,它们之和为5+5+10=20;
第二种添括号方法:
  (4+((1+2)+3))=(4+((3)+3)=(4+(6))=(10),中间和是3,6,10,它们之和为19。

输入

第一行为N(2<=n<=100),第二行依次为a1,a2,...,an(均为不大于1000的整数)。  

输出

输出仅有一行为S(最小的中间和)。

样例输入

5
10 3 5 6 8

样例输出

72

提示

和之前那个合并的一样吧。。

dp[i][j]=min(dp[i][k]+dp[k+1][j]+sum(i,j),dp[i][j])

#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <ctime>
#include <cstring>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef double db;
#define X first
#define Y second
#define mp(a,b) make_pair(a,b)
#define pb push_back
#define sd(x) scanf("%d",&(x))
#define Pi acos(-1.0)
#define sf(x) scanf("%lf",&(x))
#define ss(x) scanf("%s",(x))
#define maxn 50005
const int inf=0x3f3f3f3f;
const ll mod=1000000007;
int sum[105];
int dp[105][105];
int main()
{
#ifdef local
    freopen("in","r",stdin);
    //freopen("out","w",stdout);
    int _time=clock();
#endif
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
        {
            cin>>sum[i];
            sum[i]+=sum[i-1];
        }
    memset(dp,127/3,sizeof dp);
    for(int i=0;i<=n;i++)
    {
        dp[i][i]=0;
    }
    for(int v=1;v<n;v++)
    {
        for(int i=1;i<=n-v;i++)
        {
            int j=i+v;
            for(int k=1;k<j;k++)
            {
                dp[i][j]=min(dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1],dp[i][j]);
            }
        }
    }
    cout<<dp[1][n]<<endl;
#ifdef local
    printf("time: %d
",int(clock()-_time));
#endif
}
View Code
原文地址:https://www.cnblogs.com/scau-zk/p/5640439.html