#include <iostream>
#include <fstream>
#include <algorithm>
#include <vector>

using namespace std;

// STANDARD INPUT
//ifstream fin("window.in");
//ofstream fout("window.out");

char parse[1 << 18], *now;
void verify()
{
    if (*now == 0)
    {
        cin.get(parse, (1 << 18), '\0');
        now = parse;
    }
}
int getnum()
{
    while (*now < '0' || *now > '9')
    {
        ++now;
        verify();
    }

    int num = 0;
    while (*now >= '0' && *now <= '9')
    {
        num = num * 10 + (*now - '0');
        ++now;
        verify();
    }

    return num;
}

int N;
int A[2002][2002];
int lf[2002][2002], up[2002][2002], rg[2002][2002], dw[2002][2002];
int M1[2002][2002], M2[2002][2002];
int D[2002], E[2002];
int pos1[2002], pos2[2002];
int result, px, py;

inline bool compareA(const int& i1, const int& i2)
{
    return D[i1] < D[i2];
}
inline bool compareB(const int& i1, const int& i2)
{
    return E[i1] < E[i2];
}

vector<int> V[2002], W[2002];
int T[2002], H[2002], LF[2002], RG[2002], P[2002];

int Find(int x)
{
    if (T[T[x]] != T[x]) T[x] = Find(T[x]);
    return T[x];
}
void Unite(int x, int y)
{
    if (H[x] < H[y])
    {
        T[x] = y;
        LF[y] = min(LF[x], LF[y]);
        RG[y] = max(RG[x], RG[y]);
    }
    else
    {
        T[y] = x;
        LF[x] = min(LF[x], LF[y]);
        RG[x] = max(RG[x], RG[y]);
        if (H[x] == H[y])
            ++H[x];
    }
}

void getRes(int M, int sti, int stj, int type)
{
    for (int i = 0; i <= N; ++i)
    {
        V[i].clear();
        W[i].clear();
    }
    for (int i = 1; i <= M; ++i)
    {
        V[D[i]].push_back(i);
        W[E[i]].push_back(i);

        T[i] = i, H[i] = 0;
        LF[i] = RG[i] = i;
        P[i] = 1;
    }

    for (int i = 0; i <= N; ++i)
    {
        for (int j = 0; j < int(V[i].size()); ++j) // query
        {
            int now = V[i][j];
            int i1 = now, i2 = now + D[now] - 1;

            if (i1 > i2) continue;

            int frs = 0;
            if (P[i2] == 1)
                frs = i2;
            else
                frs = LF[Find(i2)] - 1;

            if (frs >= i1 && frs <= i2 && frs - i1 + 1 >= result)
            {
                result = frs - i1 + 1;
                if (type == 0)
                {
                    px = sti + i1 - 1;
                    py = stj + i1 - 1;
                }
                else
                {
                    px = sti + (M - i2 + 1) - 1;
                    py = stj + (M - i2 + 1) - 1;
                }
            }
        }
        for (int j = 0; j < int(W[i].size()); ++j) // erase
        {
            P[W[i][j]] = 0;
            if (W[i][j] != 1 && P[W[i][j] - 1] == 0)
                Unite(Find(W[i][j] - 1), Find(W[i][j]));
            if (W[i][j] != M && P[W[i][j] + 1] == 0)
                Unite(Find(W[i][j]), Find(W[i][j] + 1));
        }
    }
}

int main()
{
    now = parse;
    verify();

    N = getnum();
    for (int i = 1; i <= N; ++i)
        for (int j = 1; j <= N; ++j)
            A[i][j] = getnum();

    for (int i = 1; i <= N; ++i)
        for (int j = 1; j <= N; ++j)
        {
            // lf (not dw)
            if (A[i][j] != A[i + 1][j])
                lf[i][j] = lf[i][j - 1] + 1;
            // up (not rg)
            if (A[i][j] != A[i][j + 1])
                up[i][j] = up[i - 1][j] + 1;
        }
    for (int i = N; i >= 1; --i)
        for (int j = N; j >= 1; --j)
        {
            // rg (not up)
            if (A[i][j] != A[i - 1][j])
                rg[i][j] = rg[i][j + 1] + 1;
            // dw (not lf)
            if (A[i][j] != A[i][j - 1])
                dw[i][j] = dw[i + 1][j] + 1;
        }

    for (int i = 1; i <= N; ++i)
        for (int j = 1; j <= N; ++j)
        {
            M1[i][j] = min(rg[i][j], dw[i][j]);
            M2[i][j] = min(lf[i][j], up[i][j]);
        }

    for (int i = 1; i <= 2 * N - 1; ++i) // (i, 1)
    {
        int pi, pj;
        if (i <= N)
        {
            pi = i;
            pj = 1;
        }
        else
        {
            pi = 1;
            pj = i - N + 1;
        }

        int tot = 0;
        for (int k = 1; pi + k < N && pj + k < N; ++k)
        {
            ++tot;
            D[tot] = M1[pi + k][pj + k];
            E[tot] = M2[pi + k][pj + k];
        }

        getRes(tot, pi + 1, pj + 1, 0);

        if (N > 1000)
        {
            reverse(D + 1, D + tot + 1);
            reverse(E + 1, E + tot + 1);

            for (int k = 1; k <= tot; ++k)
                swap(D[k], E[k]);

            getRes(tot, pi + 1, pj + 1, 1);
        }
    }

    cout << result << ' ' << px << ' ' << py << '\n';

    //cin.close();
    //cout.close();
}
