#include <iostream>
#define N 100
using namespace std;
//类似于矩阵连乘
int sum=4;//石子的堆数量
int stone[5];//第i堆石子的石子数量
int stone_min[5][5];//定义为第i堆石子到第j堆石子合并后的最少总分数 最优值存储数组 求两个堆之间合并最小值
int stone_max[5][5];//同样是最优值存储数组 只不过是存两个堆之间最大的值
int min=0;//最小值
int max=0;//最大值
int min2=0;
int max2=0;
int MatrixChain_min()//构造最小值矩阵 第i堆石子到第j堆石子合并后的最少总分数
{
int i,j;
int count=0;
for(i=1;i<=sum;i++)//初始化一下矩阵
{
for(j=1;j<=sum;j++)
{
stone_min[i][j]=-1;
}
}
for(i=1;i<=sum;i++)
{
stone_min[i][i]= 0;//自己与自己合并都为0
}
for(i=1;i<=sum-1;i++)//相邻两个堆合并的时候
{
j = i+1;
stone_min[i][j] = stone[i] +stone[j];
}
for(int r = 3;r<=sum;r++)//合并长度为3 以及以上的时候
{
for(i=1;i<=sum-r+1;i++)//计算m[i][j]的最优值之一 i一直向右合并 没有分割两个堆再合并 i定了j不断的扩大 扫到更多的范围
{
j = i+r-1;//j距离i r-1的距离
count =0;
for(int b=i;b<=j;b++)
count += stone[b];
stone_min[i][j] = stone_min[i+1][j] +count;
for(int k=i+1;k<j;k++)//分割两块 与上面进行比较 取最优的是最小值
{
int t = stone_min[i][k]+stone_min[k+1][j]+ count;
if(t<stone_min[i][j])
stone_min[i][j] = t;//当这个分割的时候更小 则用这个
}
}//每个循环都算出了当前长度的最优值
}
return stone_min[1][sum];
}
int MatrixChain_max()//构造最小值矩阵 第i堆石子到第j堆石子合并后的最少总分数
{
int i,j,r;
int count;
for(i=1;i<=sum;i++)
{
for(j=1;j<=sum;j++)
{
stone_max[i][j]=-1;
}
}
for(i=1;i<=sum;i++)
{
stone_max[i][i]=0;
}
for(i=1;i<=sum-1;i++)
{
j=i+1;
stone_max[i][j]=stone[i]+stone[j];
}
for(r=3;r<=sum;r++)
{
for(i=1;i<=sum-r+1;i++)
{
count =0;
j = i+r-1;//j距离i r-1个长度
for(int b =i;b<=j;b++)
count +=stone[b];
stone_max[i][j]=stone_max[i+1][j]+count;
for(int k=i+1;k<j;k++)
{
int t = stone_max[i][k]+stone_max[k+1][j]+count;
if(t>stone_max[i][j])
stone_max[i][j] =t ;
}
}
}
return stone_max[1][sum];
}
int main()
{
int first = 0;
int j;
scanf("%d",&sum);
for(int i=1;i<=sum;i++)
{
scanf("%d",&stone[i]);
}
min = MatrixChain_min();
max = MatrixChain_max();
printf("%3d\n",min);
printf("%3d\n",max);
for(i=1;i<=sum;i++)
{
for(j=1;j<=sum;j++)
{
printf("%3d",stone_min[i][j]);
}
printf("\n");
}
printf("\n");
for(i=1;i<=sum;i++)
{
for(j=1;j<=sum;j++)
{
printf("%3d",stone_max[i][j]);
}
printf("\n");
}
for( j=1;j<=sum-1;j++)//考虑到圆的因素 每个元素都可以作为横着表示开头 所以有n种情况
{
min2 = 0;
max2 = 0;
first = stone[1];
for(int k =2;k<=sum;k++)
stone [k-1] = stone[k];
stone[sum] = first;
min2 = MatrixChain_min();
max2 = MatrixChain_max();
if(min2<min)
min = min2;
if(max2>max)
max = max2;
}
printf("%d\n",min);
printf("%d\n",max);
return 1;
}
#define N 100
using namespace std;
//类似于矩阵连乘
int sum=4;//石子的堆数量
int stone[5];//第i堆石子的石子数量
int stone_min[5][5];//定义为第i堆石子到第j堆石子合并后的最少总分数 最优值存储数组 求两个堆之间合并最小值
int stone_max[5][5];//同样是最优值存储数组 只不过是存两个堆之间最大的值
int min=0;//最小值
int max=0;//最大值
int min2=0;
int max2=0;
int MatrixChain_min()//构造最小值矩阵 第i堆石子到第j堆石子合并后的最少总分数
{
int i,j;
int count=0;
for(i=1;i<=sum;i++)//初始化一下矩阵
{
for(j=1;j<=sum;j++)
{
stone_min[i][j]=-1;
}
}
for(i=1;i<=sum;i++)
{
stone_min[i][i]= 0;//自己与自己合并都为0
}
for(i=1;i<=sum-1;i++)//相邻两个堆合并的时候
{
j = i+1;
stone_min[i][j] = stone[i] +stone[j];
}
for(int r = 3;r<=sum;r++)//合并长度为3 以及以上的时候
{
for(i=1;i<=sum-r+1;i++)//计算m[i][j]的最优值之一 i一直向右合并 没有分割两个堆再合并 i定了j不断的扩大 扫到更多的范围
{
j = i+r-1;//j距离i r-1的距离
count =0;
for(int b=i;b<=j;b++)
count += stone[b];
stone_min[i][j] = stone_min[i+1][j] +count;
for(int k=i+1;k<j;k++)//分割两块 与上面进行比较 取最优的是最小值
{
int t = stone_min[i][k]+stone_min[k+1][j]+ count;
if(t<stone_min[i][j])
stone_min[i][j] = t;//当这个分割的时候更小 则用这个
}
}//每个循环都算出了当前长度的最优值
}
return stone_min[1][sum];
}
int MatrixChain_max()//构造最小值矩阵 第i堆石子到第j堆石子合并后的最少总分数
{
int i,j,r;
int count;
for(i=1;i<=sum;i++)
{
for(j=1;j<=sum;j++)
{
stone_max[i][j]=-1;
}
}
for(i=1;i<=sum;i++)
{
stone_max[i][i]=0;
}
for(i=1;i<=sum-1;i++)
{
j=i+1;
stone_max[i][j]=stone[i]+stone[j];
}
for(r=3;r<=sum;r++)
{
for(i=1;i<=sum-r+1;i++)
{
count =0;
j = i+r-1;//j距离i r-1个长度
for(int b =i;b<=j;b++)
count +=stone[b];
stone_max[i][j]=stone_max[i+1][j]+count;
for(int k=i+1;k<j;k++)
{
int t = stone_max[i][k]+stone_max[k+1][j]+count;
if(t>stone_max[i][j])
stone_max[i][j] =t ;
}
}
}
return stone_max[1][sum];
}
int main()
{
int first = 0;
int j;
scanf("%d",&sum);
for(int i=1;i<=sum;i++)
{
scanf("%d",&stone[i]);
}
min = MatrixChain_min();
max = MatrixChain_max();
printf("%3d\n",min);
printf("%3d\n",max);
for(i=1;i<=sum;i++)
{
for(j=1;j<=sum;j++)
{
printf("%3d",stone_min[i][j]);
}
printf("\n");
}
printf("\n");
for(i=1;i<=sum;i++)
{
for(j=1;j<=sum;j++)
{
printf("%3d",stone_max[i][j]);
}
printf("\n");
}
for( j=1;j<=sum-1;j++)//考虑到圆的因素 每个元素都可以作为横着表示开头 所以有n种情况
{
min2 = 0;
max2 = 0;
first = stone[1];
for(int k =2;k<=sum;k++)
stone [k-1] = stone[k];
stone[sum] = first;
min2 = MatrixChain_min();
max2 = MatrixChain_max();
if(min2<min)
min = min2;
if(max2>max)
max = max2;
}
printf("%d\n",min);
printf("%d\n",max);
return 1;
}