#include <bits/stdc++.h>
#pragma GCC optimize(3)
using namespace std;
#define iinf 2000000000
#define linf 1000000000000000000LL
#define ulinf 10000000000000000000ull
#define MOD1 1000000007LL
#define mpr make_pair
typedef long long LL;
typedef unsigned long long ULL;
typedef unsigned long UL;
typedef unsigned short US;
typedef pair < int , int > pii;
clock_t __stt;
inline void TStart(){__stt=clock();}
inline void TReport(){printf("\nTaken Time : %.3lf sec\n",(double)(clock()-__stt)/CLOCKS_PER_SEC);}
template < typename T > T MIN(T a,T b){return a<b?a:b;}
template < typename T > T MAX(T a,T b){return a>b?a:b;}
template < typename T > T ABS(T a){return a>0?a:(-a);}
template < typename T > void UMIN(T &a,T b){if(b<a) a=b;}
template < typename T > void UMAX(T &a,T b){if(b>a) a=b;}
int n,g[505][505],s[505][505],mx[505];
bool e[505][505];
LL res;
int readchar(){
	char c=getchar();
	while(c==' ' || c=='\n') c=getchar();
	if(c=='#') return 0;
	return c-'0';
}
namespace DSU{
	int fa[250005],rk[250005];
	void init(){
		int i;
		memset(rk,0,sizeof(rk));
		for(i=0;i<=n*n;++i) fa[i]=i;
	}
	int ancestor(int x){
		if(fa[x]!=x) fa[x]=ancestor(fa[x]);
		return fa[x];
	}
	void unite(int u,int v){
		u=ancestor(u);
		v=ancestor(v);
		if(rk[u]<rk[v])
			fa[u]=v;
		else if(rk[u]>rk[v])
			fa[v]=u;
		else{
			fa[u]=v;
			++rk[v];
		}
	}
	bool con(int u,int v){
		return 1;
		return ancestor(u)==ancestor(v);
	}
};
void add(int x,int y){
	e[x][y]=1;
	if(e[x-1][y]) DSU::unite(x*n+y,(x-1)*n+y);
	if(e[x][y-1]) DSU::unite(x*n+y-1,x*n+y);
	if(e[x+1][y]) DSU::unite(x*n+y,(x+1)*n+y);
	if(e[x][y+1]) DSU::unite(x*n+y+1,x*n+y);
	if(x<n-1 && g[x+1][y] && !e[x+1][y]) add(x+1,y);
	if(y<n-1 && g[x][y+1] && !e[x][y+1]) add(x,y+1);
}
int getlower(int x,int y){
	int cx=x,cy=y,ret=(y?s[x][y-1]:0);
	mx[y]=x;
	while(1){
		while(1){
			if(cx+1<n && e[cx+1][cy]){
				++cx;
				mx[y]=cx;
				ret+=(cy?s[cx][cy-1]:0);
			}
			else if(cy+1<n && e[cx][cy+1]){
				++cy;
			}
			else break;
		}
		bool found=0;
		while(cy+1<n){
			++cy;
			if(e[cx][cy] && DSU::con(cx*n+cy,x*n+y)){
				found=1;
				break;
			}
			else if(e[cx][cy]) break;
		}
		if(!found) break;
	}
	return ret;
}
int getupper(int x,int y){
	int cx=x,cy=y,ret=0;
	while(1){
		while(1){
			if(cy+1<n && e[cx][cy+1]){
				++cy;
			}
			else if(cx+1<n && e[cx+1][cy]){
				ret+=s[cx][cy];
				++cx;
			}
			else break;
		}
		bool found=0;
		while(cx<n-1){
			ret+=s[cx][cy];
			++cx;
			if(cx>mx[y]) break;
			if(e[cx][cy] && DSU::con(cx*n+cy,x*n+y)){
				found=1;
				break;
			}
			else if(e[cx][cy]) break;
		}
		if(!found || cx>mx[y]) break;
	}
	if(cx<=mx[y]) ret+=s[cx][cy];
	return ret;
}
void solveline(int x){
	int i,j,k;
	memcpy(s,g,sizeof(g));
	for(i=0;i<n;++i){
		for(j=1;j<n;++j){
			s[i][j]+=s[i][j-1];
		}
	}
	DSU::init();
	for(i=x;i<n;++i) memset(e[i],0,sizeof(e[i]));
	for(i=0;i<n;++i){
		if(!g[x][i]) continue;
		add(x,i);
		res-=(LL)g[x][i]*(LL)getlower(x,i);
	}
	DSU::init();
	for(i=x;i<n;++i) memset(e[i],0,sizeof(e[i]));
	for(i=n-1;i>=0;--i){
		if(!g[x][i]) continue;
		add(x,i);
		res+=(LL)g[x][i]*(LL)(getupper(x,i)-g[x][i]);
	}
}
void del(int x,int y){
	if((!x || !g[x-1][y]) && (!y || !g[x][y-1])){
		g[x][y]=0;
		if(x<n-1 && g[x+1][y]) del(x+1,y);
		if(y<n-1 && g[x][y+1]) del(x,y+1);
	}
}
int main(){
    // inputting start
    // 数据结构记得初始化！ n，m别写反！
    int i,j,k;
	scanf("%d",&n);
	for(i=0;i<n;++i){
		for(j=0;j<n;++j){
			g[i][j]=readchar();
		}
	}
    #ifdef LOCAL
        TStart();
    #endif
    // calculation start
    // 数据结构记得初始化！ n，m别写反！
	for(i=0;i<n;++i){
		for(j=0;j<n;++j){
			e[i][j]=(!!g[i][j]);
		}
	}
    for(i=n-1;i>=0;--i){
		solveline(i);
		for(j=0;j<n;++j){
			if(g[i][j]) del(i,j);
		}
	}
	printf("%lld\n",res);
    #ifdef LOCAL
        TReport();
    #endif
    return 0;
}

Measured memory_bytes: 4608