#include <bits/stdc++.h>

using vi = std::vector<int64_t>;
using vvi = std::vector<vi>;

int H, W, N;
vvi values;

int topFind(int, int, int, int, int64_t);
int bottomFind(int, int, int, int, int64_t);
int leftFind(int, int, int, int, int64_t);
int rightFind(int, int, int, int, int64_t);
bool condition(int, int, int, int, int, int64_t);
int64_t calcArea(int, int, int, int);

int main()
{
	scanf("%d%d%d", &H, &W, &N);
	values.resize(H + 1, vi(W + 1));
	for (int i{1}; i <= H; i++)
		for (int j{1}; j <= W; j++)
			scanf("%lld", &values[i][j]);
	for (int i{1}; i <= H; i++)
		for (int j{1}; j <= W; j++)
			values[i][j] += values[i][j - 1];
	for (int i{1}; i <= W; i++)
		for (int j{1}; j<= H; j++)
			values[j][i] += values[j - 1][i];
	int64_t ng{1ll << 60}, ok{};
	while (ng - ok > 1)
	{
		int64_t mid{(ok + ng) >> 1};
		if (condition(0, 0, H, W, N, mid)) ok = mid;
		else ng = mid;
	}
	printf("%lld\n", ok);
	
	return 0;
}

bool condition(int top, int left, int bottom, int right, int N, int64_t lowbou)
{
	if (N == 0) return true;
	if (calcArea(top, left, bottom, right) < N * lowbou) return false;
	int midtop{topFind(top, left, bottom, right, lowbou)}, midleft{leftFind(top, left, bottom, right, lowbou)};
	int midbottom{bottomFind(top, left, bottom, right, lowbou)}, midright{rightFind(top, left, bottom, right, lowbou)};
	if (condition(midtop, left, bottom, right, N - 1, lowbou) || condition(top, midleft, bottom, right, N - 1, lowbou)
		|| condition(top, left, midbottom, right, N - 1, lowbou) || condition(top, left, bottom, midright, N - 1, lowbou)
		)
		return true;
	if (N <= 3) return false;
	for (int h_i{1}; h_i <= H; h_i++)
	{
		if (calcArea(0, 0, h_i, W) < lowbou) continue;
		int r{rightFind(0, 0, h_i, W, lowbou)};
		if (calcArea(0, 0, H, r) < lowbou) continue;
		int t{std::max(h_i, topFind(0, 0, H, r, lowbou))};
		if (calcArea(t, 0, H, W) < lowbou) continue;
		int l{std::max(r, leftFind(t, 0, H, W, lowbou))};

		if (calcArea(h_i, l, H, W) >= lowbou) return true;
	}
	for (int h_i{1}; h_i <= H; h_i++)
	{
		if (calcArea(0, 0, h_i, W) < lowbou) continue;
		int l{leftFind(0, 0, h_i, W, lowbou)};
		if (calcArea(0, l, H, W) < lowbou) continue;
		int t{std::max(h_i, topFind(0, l, H, W, lowbou))};
		if (calcArea(t, 0, H, W) < lowbou) continue;
		int r{std::min(l, rightFind(t, 0, H, W, lowbou))};

		if (calcArea(h_i, 0, H, r) >= lowbou) return true;
	}
	return false;
}

int topFind(int top, int left, int bottom, int right, int64_t lowbou)
{
	int ng{top - 1}, ok{bottom};
	while (ok - ng > 1)
	{
		int mid{(ok + ng) >> 1};
		if (calcArea(top, left, mid, right) >= lowbou)
			ok = mid;
		else
			ng = mid;
	}
	return ok;
}

int leftFind(int top, int left, int bottom, int right, int64_t lowbou)
{
	int ng{left - 1}, ok{right};
	while (ok - ng > 1)
	{
		int mid{(ok + ng) >> 1};
		if (calcArea(top, left, bottom, mid) >= lowbou)
			ok = mid;
		else
			ng = mid;
	}
	return ok;
}

int bottomFind(int top, int left, int bottom, int right, int64_t lowbou)
{
	int ok{top}, ng{bottom + 1};
	while (ng - ok > 1)
	{
		int mid{(ok + ng) >> 1};
		if (calcArea(mid, left, bottom, right) >= lowbou)
			ok = mid;
		else
			ng = mid;
	}
	return ok;
}

int rightFind(int top, int left, int bottom, int right, int64_t lowbou)
{
	int ok{left}, ng{right + 1};
	while (ng - ok > 1)
	{
		int mid{(ok + ng) >> 1};
		if (calcArea(top, mid, bottom, right) >= lowbou)
			ok = mid;
		else
			ng = mid;
	}
	return ok;
}

int64_t calcArea(int top, int left, int bottom, int right)
{
	return values[bottom][right] + values[top][left] - values[bottom][left] - values[top][right];
}


Measured memory_bytes: 3400