Problem:
Score : 1000 points

Problem Statement

Problem F and F2 are the same problem, but with different constraints and time limits.

We have a board divided into N horizontal rows and N vertical columns of square cells.
The cell at the i-th row from the top and the j-th column from the left is called Cell (i,j).
Each cell is either empty or occupied by an obstacle.
Also, each empty cell has a digit written on it.
If A_{i,j}= 1, 2, ..., or 9, Cell (i,j) is empty and the digit A_{i,j} is written on it.
If A_{i,j}= #, Cell (i,j) is occupied by an obstacle.

Cell Y is reachable from cell X when the following conditions are all met:

Cells X and Y are different.

Cells X and Y are both empty.

One can reach from Cell X to Cell Y by repeatedly moving right or down to an adjacent empty cell.

Consider all pairs of cells (X,Y) such that cell Y is reachable from cell X.
Find the sum of the products of the digits written on cell X and cell Y for all of those pairs.

Constraints

1 \leq N \leq 500

A_{i,j} is one of the following characters: 1, 2, ... 9 and #.

Input

Input is given from Standard Input in the following format:

N
A_{1,1}A_{1,2}...A_{1,N}
A_{2,1}A_{2,2}...A_{2,N}
:
A_{N,1}A_{N,2}...A_{N,N}

Output

Print the sum of the products of the digits written on cell X and cell Y for all pairs (X,Y) such that cell Y is reachable from cell X.

Sample Input 1

2
11
11

Sample Output 1

5

There are five pairs of cells (X,Y) such that cell Y is reachable from cell X, as follows:

X=(1,1), Y=(1,2)

X=(1,1), Y=(2,1)

X=(1,1), Y=(2,2)

X=(1,2), Y=(2,2)

X=(2,1), Y=(2,2)

The product of the digits written on cell X and cell Y is 1 for all of those pairs, so the answer is 5.

Sample Input 2

4
1111
11#1
1#11
1111

Sample Output 2

47

Sample Input 3

10
76##63##3#
8445669721
75#9542133
3#285##445
749632##89
2458##9515
5952578#77
1#3#44196#
4355#99#1#
#298#63587

Sample Output 3

36065

Sample Input 4

10
4177143673
7#########
5#1716155#
6#4#####5#
2#3#597#6#
6#9#8#3#5#
5#2#899#9#
1#6#####6#
6#5359657#
5#########

Sample Output 4

6525

Solution in C# (Mono 4.6.2.0) (judge verdict: Time Limit Exceeded)

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Text;
using System.Globalization;
using System.Diagnostics;
using System.Threading.Tasks;



class Myon
{
    public Myon() { }
    public static int Main()
    {
        new Myon().calc();
        return 0;
    }

    Scanner cin;

    int[] vy = { 1, 0, -1, 0 };
    int[] vx = { 0, 1, 0, -1 };

    int N;

    void calc()
    {
        cin = new Scanner();
        N = cin.nextInt();

        string[] board = new string[N];
        for (int i = 0; i < N; i++)
        {
            board[i] = cin.next();
            //board[i] = new string('9', N);
        }
        int[,] numBoard = new int[N, N];
        for (int i = 0; i < N; i++)
        {
            for (int j = 0; j < N; j++)
            {
                if (board[i][j] == '#') numBoard[i, j] = -1;
                else numBoard[i, j] = (int)(board[i][j] - '0');
            }
        }

        Queue<int> q = new Queue<int>();

        bool[,] startUsed = new bool[N, N];

        for (int sy = N - 1; sy >= 0; sy--)
        {
            for (int sx = N - 1; sx >= 0; sx--)
            {
                if (!startUsed[sy, sx] && numBoard[sy, sx] != -1)
                {
                    Queue<int> q2 = new Queue<int>();
                    q2.Enqueue((sy << 12) + sx);

                    while (q2.Count != 0)
                    {
                        int now = q2.Dequeue();
                        int y = now >> 12;
                        int x = now & 0xFFF;
                        if (!startUsed[y, x])
                        {
                            startUsed[y, x] = true;
                            q.Enqueue(now);
                            q2.Clear();
                        }

                        for (int k = 2; k < 4; k++)
                        {
                            int ny = y + vy[k];
                            int nx = x + vx[k];
                            if (inside(ny, nx) && numBoard[ny, nx] != -1)
                            {
                                q2.Enqueue((ny << 12) + nx);
                            }
                        }
                    }
                    q.Enqueue(-1);
                }
            }
        }

        int[,] used = new int[N, N];
        int myTurn = 1;

        long ans = 0;
        long nowSum = 0;

        while (q.Count != 0)
        {
            int start = q.Dequeue();

            if(start == -1)
            {
                myTurn++;
                nowSum = 0;
                //Console.Error.WriteLine("reset");
                continue;
            }

            Queue<int> q2 = new Queue<int>();
            int sy = start >> 12;
            int sx = start & 0xFFF;
            used[sy, sx] = myTurn;
            q2.Enqueue(start);


            while (q2.Count != 0)
            {
                int now = q2.Dequeue();
                int y = now >> 12;
                int x = now & 0xFFF;
                nowSum += numBoard[y, x];

                for (int k = 0; k <= 1; k++)
                {
                    int ny = y + vy[k];
                    int nx = x + vx[k];
                    if (inside(ny, nx) && numBoard[ny, nx] != -1 && used[ny,nx] != myTurn)
                    {
                        used[ny, nx] = myTurn;
                        q2.Enqueue((ny << 12) + nx);
                    }
                }
            }

            //Console.Error.WriteLine(sy + " " + sx + " " + nowSum);

            ans += numBoard[sy, sx] * nowSum;
        }

        for (int i = 0; i < N; i++)
        {
            for (int j = 0; j < N; j++)
            {
                if (numBoard[i, j] != -1) ans -= numBoard[i, j] * numBoard[i, j];
            }
        }

        Console.WriteLine(ans);
    }

    bool inside(int y, int x)
    {
        return y >= 0 && x >= 0 && y < N && x < N;
    } 
}



class Scanner
{
    string[] s;
    int i;

    char[] cs = new char[] { ' ' };

    public Scanner()
    {
        s = new string[0];
        i = 0;
    }

    public string next()
    {
        if (i < s.Length) return s[i++];
        string st = Console.ReadLine();
        while (st == "") st = Console.ReadLine();
        s = st.Split(cs, StringSplitOptions.RemoveEmptyEntries);
        if (s.Length == 0) return next();
        i = 0;
        return s[i++];
    }

    public int nextInt()
    {
        return int.Parse(next());
    }
    public int[] ArrayInt(int N, int add = 0)
    {
        int[] Array = new int[N];
        for (int i = 0; i < N; i++)
        {
            Array[i] = nextInt() + add;
        }
        return Array;
    }

    public long nextLong()
    {
        return long.Parse(next());
    }

    public long[] ArrayLong(int N, long add = 0)
    {
        long[] Array = new long[N];
        for (int i = 0; i < N; i++)
        {
            Array[i] = nextLong() + add;
        }
        return Array;
    }

    public double nextDouble()
    {
        return double.Parse(next());
    }


    public double[] ArrayDouble(int N, double add = 0)
    {
        double[] Array = new double[N];
        for (int i = 0; i < N; i++)
        {
            Array[i] = nextDouble() + add;
        }
        return Array;
    }
}