Gargari is jealous that his friend Caisa won the game from the previous problem. He wants to prove that he is a genius.

He has a n × n chessboard. Each cell of the chessboard has a number written on it. Gargari wants to place two bishops on the chessboard in such a way that there is no cell that is attacked by both of them. Consider a cell with number x written on it, if this cell is attacked by one of the bishops Gargari will get x dollars for it. Tell Gargari, how to place bishops on the chessboard to get maximum amount of money.

We assume a cell is attacked by a bishop, if the cell is located on the same diagonal with the bishop (the cell, where the bishop is, also considered attacked by it).

Input

The first line contains a single integer n (2 ≤ n ≤ 2000). Each of the next n lines contains n integers aij (0 ≤ aij ≤ 109) — description of the chessboard.

Output

On the first line print the maximal number of dollars Gargari will get. On the next line print four integers: x1, y1, x2, y2 (1 ≤ x1, y1, x2, y2 ≤ n), where xi is the number of the row where the i-th bishop should be placed, yi is the number of the column where the i-th bishop should be placed. Consider rows are numbered from 1 to n from top to bottom, and columns are numbered from 1 to n from left to right.

If there are several optimal solutions, you can print any of them.

Examples

Input

4
1 1 1 1
2 1 1 0
1 1 1 0
1 0 0 1


Output

12
2 2 3 2
import java.io.*; 
import java.lang.reflect.Array; 
import java.math.BigDecimal;
import java.math.BigInteger; 
import java.sql.Time;
import java.util.*; 
import java.util.Map.Entry;

import static java.lang.Math.*; 
   
public class solver implements Runnable { 
        final boolean ONLINE_JUDGE = System.getProperty("ONLINE_JUDGE") != null; 
        BufferedReader in; 
        PrintWriter out; 
        StringTokenizer tok = new StringTokenizer(""); 
        
        boolean HasTokens(){
            while(!tok.hasMoreTokens()){ 
                try{ 
                        tok = new StringTokenizer(in.readLine()); 
                }catch (Exception e){ 
                        return false; 
                } 
            }
            return true;
        }
          
        String readString() throws IOException{                 
            return HasTokens() ? tok.nextToken():null; 
        } 
        String readString(String delim) throws IOException{ 
            return HasTokens() ? tok.nextToken(delim):null;
        } 
         
        int readInt() throws IOException{ 
            return Integer.parseInt(readString()); 
        }   
        long readLong() throws IOException{ 
            return Long.parseLong(readString()); 
        }       
        double readDouble() throws IOException{ 
            return Double.parseDouble(readString()); 
        }  
        char readChar() throws IOException { 
            char val = 0; 
            do{ 
                val = (char) in.read(); 
            }while(val == '\n' || val == '\r'); 
            return val; 
        } 
        char readChar(String skipChars)throws IOException{ 
            char val = 0; 
            boolean ret; 
            do{ 
                val = (char) in.read(); 
                ret = false; 
                for (int i = skipChars.length()-1; i >= 0; i--){ 
                    if (skipChars.charAt(i) == val){ 
                        ret = true; 
                        break; 
                    } 
                } 
            }while(ret); 
            return val; 
        }
//----------------------------------
        int gcd(int x, int y){
            while (y != 0) {
                int temp = x%y; x = y; y = temp;
            }
            return x;
        }
//----------------------------------        
          
        public class Pair<T1,T2> { 
            public T1 x1; 
            public T2 x2; 
            public Pair(){}; 
            public Pair(T1 x1, T2 x2){ 
                this.x1 = x1; 
                this.x2 = x2; 
            } 
            public String toString(){ 
                return x1 + ":" + x2; 
            } 
        } 
        public class Point implements Comparable<Point>{ 
            public int x2; int x1; 
            public Point(){} 
            public Point(int a, int b){x1 = a;x2=b;} 
            public int compareTo(Point o) {
                return (int)-(x1*x2 - o.x1*o.x2); 
                //if (x1 == o.x1) return -(x2 -o.x2);
                //return (x1-o.x1);  
                // (x1-o.x1) - increase; -(x1-o.x1) - decrease 
            } 
            public String toString(){ 
                return x1 + ":" + x2; 
            } 
            @Override
            public int hashCode() {
                final int prime = 31;
                int result = 1;
                result = prime * result + getOuterType().hashCode();
                result = prime * result + x1;
                result = prime * result + x2;
                return result;
            }
            @Override
            public boolean equals(Object obj) {
                if (this == obj)
                    return true;
                if (obj == null)
                    return false;
                if (getClass() != obj.getClass())
                    return false;
                Point other = (Point) obj;
                if (!getOuterType().equals(other.getOuterType()))
                    return false;
                if (x1 != other.x1)
                    return false;
                if (x2 != other.x2)
                    return false;
                return true;
            }
            private solver getOuterType() {
                return solver.this;
            }
        } 
        public class Three implements Comparable<Three>{ 
            public int x1, x2, x3; 
            public Three(){} 
            public Three(int a, int b, int c){x1 = a;x2=b;x3=c;} 
            public int compareTo(Three o) {
                if(x1 == o.x1 && x2 == o.x2) return x3-o.x3;
                if(x1 == o.x1) return x2-o.x2;
                return (x1-o.x1);  
                // (x1-o.x1) - increase; -(x1-o.x1) - decrease 
            } 
            public String toString(){ 
                return x1 + ":" + x2 + ":" + x3; 
            } 
        } 
//----------------------------------------     
        
        public void solve() throws IOException {        
            
            int n = readInt();
            int[][] a = new int[n][n];
            long[][] b = new long[n][n];
            
            int z = 2*n - 1;
            long[] lr = new long[z];
            long[] rl = new long[z];
            
            for (int i = 0; i < n; i++){
                for (int j = 0 ; j < n; j++){
                    a[i][j] = readInt();
                    int x = GetLR(i, j, n);
                    int y = GetRL(i, j, n);
                    lr[x] += a[i][j];
                    rl[y] += a[i][j];
                }
            }
            
            long m1 = 0, m2 = 0;
            
            int x1 = 0, y1 = 0,
                    x2 = 1, y2 = 0;
            
            for (int i = 0; i < n; i++){
                for (int j = 0 ; j < n; j++){
                    b[i][j] = lr[GetLR(i, j, n)] + rl[GetRL(i, j, n)] - a[i][j];
                    if ((i+j) % 2 != 0 && b[i][j] > m1){
                        m1 = b[i][j];
                        x1 = i;
                        y1 = j;
                    }
                    if ((i+j)%2 == 0 && b[i][j] > m2){
                        m2 = b[i][j];
                        x2 = i;
                        y2 = j;
                    }
                }
            }
            x1++;x2++;
            y1++;y2++;
            
            out.println(m1+m2);
            out.print(x1 + " " + y1 + " " + x2 + " " + y2);
        }
        
        int GetLR(int i , int j, int n){
            return i+j;
        }
        int GetRL(int i , int j, int n){
            return (n-i-1)+j;
        }
        
//---------------------------------------- 
        public static void main(String[] args){ 
                new Thread(null, new solver(), "", 256 * (1L << 20)).start(); 
        } 
         
        public void run(){ 
                try{ 
                        timeBegin = System.currentTimeMillis(); 
                        try{ 
                            if (ONLINE_JUDGE){ 
                                in = new BufferedReader(new InputStreamReader(System.in)); 
                                out = new PrintWriter(System.out); 
                            }  
                            else { 
                                in = new BufferedReader(new FileReader("input.txt")); 
                                out = new PrintWriter("output.txt"); 
                            } 
                        }catch(Throwable e){
                            in = new BufferedReader(new InputStreamReader(System.in)); 
                            out = new PrintWriter(System.out); 
                        }
                          
                        solve(); 
                        out.close(); 
                          
                        timeEnd = System.currentTimeMillis(); 
                        System.err.println("Time = " + (timeEnd - timeBegin)); 
                }catch (Exception e){ 
                        e.printStackTrace(System.err); 
                        System.exit(-1); 
                } 
        } 
         
        long timeBegin, timeEnd; 
   
          
//----------        
        void update(int[] doo, int v, int i, int val, int ll, int rr){ 
            if (ll == rr){ 
                doo[v] = val; 
            }else{ 
                int med = ll + ((rr-ll)>>1); 
                  
                if (i <= med){ 
                    update(doo, v<<1, i, val, ll, med); 
                }else{ 
                    update(doo, (v<<1)+1, i, val, med+1, rr); 
                } 
                doo[v] = min(doo[v<<1], doo[(v<<1)+1]); 
            } 
        } 
        long get(long[] doo, int v, int l, int r, int ll, int rr){ 
            if (l > r){ 
                return Integer.MAX_VALUE; 
            } 
            if (ll == l && r == rr){ 
                return doo[v]; 
            } 
            int med = ll + ((rr-ll)>>1);
            return min(get(doo, v<<1, l, min(r, med), ll, med),  
                    get(doo, (v<<1)+1, max(l, med+1), r, med+1, rr)); 
        }        
        
 //----------------------------------------

        int BinSearch(int[] a, int x, boolean increase){

            int first = 0;
            int last = a.length;
            
            if (increase){
                while (first <= last) {
                    int mid = first + ((last - first) >> 1);                
                    if (x <= a[mid])
                        last = mid;
                    else
                        first = mid + 1;
                }
                return last;
            }else{
                while (first <= last) {
                    int mid = first + ((last - first) >> 1);                
                    if (x > a[mid])
                        last = mid;
                    else
                        first = mid + 1;
                }
                return first;
            }
        }
        
        
//-----------------------------------------
}