设置m[i][j] 表示从第i个到第j个数的最小代价值,当j - i = 1(只有两个数),直接返回a[i] + a[j]。若j大于i的时候,可以随机添加括号,通过比较留下最小值。
状态方程: m[i][j] =min(dp(i,j),(dp(i,k) + dp(k+1,j) + s[j-1] - s[i-1] );
(i<=k<j)(s[0] == 0)//k为随机添加的括号
边界条件: m[i][j] = 0 ;(j == i) m[i][j] = a[i]+[j] ;( i =j+1)
空间复杂度为O(n^2),时间复杂度为O(n^3)don
动态规划将复杂的问题分解成更小的子问题,有助于理解和解决复杂问题,一般用来解决最优化问题,并且通过存储中间结果,提高效率。
#include<iostream>
#include<cstring>
using namespace std;
int n;//石头的个数
int a[108];//石头的质量
int m[108][108] = {-1};//m[i][j]表示 第i个石头到第j个石头的总代价。
int sum[108];//表示从第一个石头到第j个石头的总质量
//m[i][j] = m[i][k] + m[k+1][j] + sum[j] - sum[i-1]从第j到第i个石头的总质量 (包括第i个石头)
//m[i][j] = 0 如果i=j则没有代价
int check(int i, int j)
{
int min = 1000000;
if(m[i][j] != -1)
{
return m[i][j];
}
if(i == j)
{
m[i][j] = 0;
return m[i][j];
}
if(i+1 == j)
{
m[i][j] = a[i] + a[j];
return m[i][j];
}
else
{
for(int k=i+1; k < j; k++)
{
int cal = check(i, k) + check(k+1, j) + sum[j] - sum[i-1];
if(cal < min)
min = cal;
}
m[i][j] = min;
return m[i][j];
}
}
int main()
{
cin >> n;
sum[0] = 0;
memset(m,-1,sizeof(m));
for(int i=1; i <= n; i++)
{
cin >> a[i];
sum[i] = sum[i-1] + a[i];
//cout << sum[i] << endl;//根据这里我们可以得到sum[0]需要等于零,在前面补充
}
cout << check(1,n);
}