#define _CRT_SECURE_NO_WARNINGS
#include<iostream>

using namespace std;
const int N = 110;
int graph[N][N];
int s[N][N];//保存每一列的前缀和
int main() {
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++)
			scanf("%d", &graph[i][j]);
	//求每一列的前缀和
	for (int j = 1; j <= n; j++)
		for (int i = 1; i <= n; i++) {
			s[i][j] = s[i - 1][j] + graph[i][j];
		}

	//枚举上下边界
	int res = 0xc0c0c0c0;
	for (int i = 1; i <= n; i++)
		for (int j = i; j <= n; j++) {
			/*int f = 0;*/
			//现在要开始用dp求最大连续子序列,以第i个为一组和i个以前的为一组进行划分
			//可以得到f[i]=max(f[i-1]+w[i],w[i])
			//然后将w[i]提出来可以得到
			//max(f[i-1],0)+w[i]
			//由于每个只与上一个状态有关,所以也不用状态数组,用一个f来表示上一个状态的值即可
			int f = 0;
			for (int k = 1; k <= n; k++) {
				//k说明在两条边界之间的列好
				int w = s[j][k] - s[i - 1][k];//注意这里是s[i-1][k]
				f = max(f, 0) + w;
				res = max(f, res);
			}
		}
	printf("%d", res);
	return 0;
}