/*
典型的动态规划思想
从顶层到底层填表每次用到了上一次的最优解
跳出后在最后一行查找最大的数即可
*/
#define LOCAL
#include<iostream>
using namespace std;
#define N 100
int a[N][N], opt[N][N];
int maxsum(int n)
{
int i, j;
opt[0][0] = a[0][0];
for (i = 1; i < n; i++)
{
opt[i][0] = opt[i - 1][0] + a[i][0];
for (j = 1; j < i; j++)
if (a[i][j] + opt[i - 1][j] >= a[i][j] + opt[i - 1][j - 1])
opt[i][j] = a[i][j] + opt[i - 1][j];
else
opt[i][j] = a[i][j] + opt[i - 1][j - 1];
opt[i][i] = opt[i - 1][i - 1] + a[i][i];
}
}
int main()
{
#ifdef LOCAL
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
#endif
int i, j, t, n;
while (cin >> n)
{
memset(opt, 0, sizeof(opt));
for (i = 0; i < n; i++)
for (j = 0; j <= i; j++)
cin >> a[i][j];
maxsum(n);
//
for (i = 0; i < n; i++)
{
for (j = 0; j <= i; j++)
cout << opt[i][j] << " ";
cout << endl;
}
//
t = 0;
for (i = 0; i < n; i++)
if (t < opt[n - 1][i])
t = opt[n - 1][i]; //查找最后一行的最小值
cout << t;
}
return 0;
}