#include<bits/stdc++.h>
//#include<iostream>
//#include<cstdio>
//#include<cstring>
//#include<cstdlib>
//#include<cmath>
//#include<algorithm>
//#include<vector>
//#include<queue>
//#include<stack>
//#include<map>
//#include<set>
using namespace std;
#define SC scanf
#define PR printf
#define pb push_back
#define mp make_pair
#define SZ(v) ((int)(v).size())
#define rep(i,n) for(int i=0;i<(n);i++)
#define all(v) (v).begin(),(v).end()
#define fi first
#define se second
#define db double
#define ldb long double
#define uint unsigned
#define ll long long
typedef pair<int,int> pii;
typedef pair<pii,int> ppi;
typedef pair<int,pii> pip;
typedef pair<pii,pii> ppp;
typedef vector<int> vi;
typedef vector<bool> vb;
typedef vector<string> vs;
typedef vector<ll> vl;
typedef vector<vi> vvi;
typedef vector<pii> vii;
typedef map<int,int> mii;
const int INF=0x3f3f3f3f;
const ll LL_INF=0x3f3f3f3f3f3f3f3f;
const int xx[4]={1,-1,0,0};
const int yy[4]={0,0,1,-1};
int inline in(){
	int x=0,c;
	for(;(uint)((c=getchar())-'0')>=10;){
		if(c=='-')return -in();
		if(!~c)throw ~0;
	}
	do{
		x=(x<<3)+(x<<1)+(c-'0');
	}while((uint)((c=getchar())-'0')<10);
	return x;
}
int n,m;
string board[16];
bool vis[16][16];
void dfs(int x,int y){
	if(x<0||x>=n||y<0||y>=m||board[x][y]=='#'||vis[x][y])return;
	vis[x][y]=true;
	rep(i,4)dfs(x+xx[i],y+yy[i]);
}
int main(){
    cin.sync_with_stdio(false);cin.tie(0);
	cin>>n>>m;
	rep(i,n)cin>>board[i];
	vi init;
	int D;
	for(D=0;;D++){
		bool found=false;
		rep(i,n)rep(j,m){
			if(board[i][j]==D+'1'){
				found=true;
				init.pb(i);
				init.pb(j);
			}
		}
		if(!found)break;
	}
	cout<<D<<endl;
	dfs(init[0],init[1]);
	bool can=false;
	rep(i,n)rep(j,m)if(board[i][j]=='@'&&vis[i][j])can=true;
	if(!can){
		puts("-1");
		return 0;
	}
	map<vi,int>d;
	queue<vi>q;
	q.push(init);
	d[init]=0;
	while(!q.empty()){
		vi v=q.front();
		q.pop();
		int dis=d[v];
		rep(i,4){
			int x=v[0]+xx[i];
			int y=v[1]+yy[i];
			if(x<0||x>=n||y<0||y>=m||board[x][y]=='#')continue;
			bool bad=false;
			rep(j,D-1)if(x==v[2*j]&&y==v[2*j+1])bad=true;
			if(bad)continue;
			if(board[x][y]=='@'){
				cout<<dis+1<<endl;
				return 0;
			}
			vi w(2*D);
			w[0]=x;w[1]=y;
			rep(j,D+D-2)w[2+j]=v[j];
			if(d.find(w)==d.end()){
				d[w]=dis+1;
				q.push(w);
			}
		}
	}
	puts("-1");
	return 0;
}


#include<bits/stdc++.h>
//#include<iostream>
//#include<cstdio>
//#include<cstring>
//#include<cstdlib>
//#include<cmath>
//#include<algorithm>
//#include<vector>
//#include<queue>
//#include<stack>
//#include<map>
//#include<set>
using namespace std;
#define SC scanf
#define PR printf
#define pb push_back
#define mp make_pair
#define SZ(v) ((int)(v).size())
#define rep(i,n) for(int i=0;i<(n);i++)
#define all(v) (v).begin(),(v).end()
#define fi first
#define se second
#define db double
#define ldb long double
#define uint unsigned
#define ll long long
typedef pair<int,int> pii;
typedef pair<pii,int> ppi;
typedef pair<int,pii> pip;
typedef pair<pii,pii> ppp;
typedef vector<int> vi;
typedef vector<bool> vb;
typedef vector<string> vs;
typedef vector<ll> vl;
typedef vector<vi> vvi;
typedef vector<pii> vii;
typedef map<int,int> mii;
const int INF=0x3f3f3f3f;
const ll LL_INF=0x3f3f3f3f3f3f3f3f;
const int xx[4]={1,-1,0,0};
const int yy[4]={0,0,1,-1};
int inline in(){
	int x=0,c;
	for(;(uint)((c=getchar())-'0')>=10;){
		if(c=='-')return -in();
		if(!~c)throw ~0;
	}
	do{
		x=(x<<3)+(x<<1)+(c-'0');
	}while((uint)((c=getchar())-'0')<10);
	return x;
}
int n,m;
string s[16];
deque<pii>tp;
pii head;
char tail;
void dfs(int x,int y,int c){
	if(c==tail-'0')return;
	for(int i=0;i<4;i++){
		int dx=x+xx[i];
		int dy=y+yy[i];
		if(dx<1||dx>n||dy<1||dy>m)continue;
		if(s[dx][dy]-'0'==c+1){
			tp.push_back(mp(dx,dy));
			dfs(dx,dy,c+1);
			return;
		}
	}
}
int d[16][16];
bool vis[16][16];
//map<deque<pii>,bool>vis;
ll cnt=1;
int bfs(){
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			d[i][j]=INF;
		}
	}
	queue<deque<pii> >q;
	vis[tp[0].fi][tp[0].se]=true;
	d[tp[0].fi][tp[0].se]=0;
	q.push(tp);
	while(!q.empty()){
		deque<pii>cur=q.front();
		q.pop();
//		if(cnt%100000==0)cout<<cnt<<endl;
//		cnt++;
		if(s[cur[0].fi][cur[0].se]=='@')return d[cur[0].fi][cur[0].se];
		for(int i=0;i<4;i++){
			int dx=cur[0].fi+xx[i];
			int dy=cur[0].se+yy[i];
			if(dx<1||dx>n||dy<1||dy>m)continue;
			if(s[dx][dy]=='#')continue;

			bool ok=true;
			for(int i=1;i<tail-'0'-1;i++){
				if(dx==cur[i].fi&&dy==cur[i].se){
					ok=false;
					break;
				}
			}
			if(!ok)continue;
			if(vis[dx][dy])continue;
			vis[dx][dy]=true;
			tp=cur;
			tp.pop_back();
			tp.push_front(mp(dx,dy));
//			if(vis[tp])continue;
//			vis[tp]=true;
			d[dx][dy]=d[cur[0].fi][cur[0].se]+1;
			q.push(tp);
		}
	}
	return -1;
}
int main(){
	cin.sync_with_stdio(false);cin.tie(0);
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>s[i];
		s[i]='#'+s[i];
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			if(s[i][j]=='1'){
				head=mp(i,j);
			}
			else if(s[i][j]>='1'&&s[i][j]<='9'){
				tail=max(tail,s[i][j]);
			}
		}
	}
	tp.push_back(head);
	dfs(head.fi,head.se,1);
//	for(int i=0;i<SZ(tp);i++)cout<<tp[i].fi<<' '<<tp[i].se<<endl;
	cout<<bfs()<<endl;
	return 0;
}


#include<bits/stdc++.h>
//#include<iostream>
//#include<cstdio>
//#include<cstring>
//#include<cstdlib>
//#include<cmath>
//#include<algorithm>
//#include<vector>
//#include<queue>
//#include<stack>
//#include<map>
//#include<set>
using namespace std;
#define SC scanf
#define PR printf
#define pb push_back
#define mp make_pair
#define SZ(v) ((int)(v).size())
#define rep(i,n) for(int i=0;i<(n);i++)
#define all(v) (v).begin(),(v).end()
#define fi first
#define se second
#define db double
#define ldb long double
#define uint unsigned
#define ll long long
typedef pair<int,int> pii;
typedef pair<pii,int> ppi;
typedef pair<int,pii> pip;
typedef pair<pii,pii> ppp;
typedef vector<int> vi;
typedef vector<bool> vb;
typedef vector<string> vs;
typedef vector<ll> vl;
typedef vector<vi> vvi;
typedef vector<pii> vii;
typedef map<int,int> mii;
const int INF=0x3f3f3f3f;
const ll LL_INF=0x3f3f3f3f3f3f3f3f;
const int xx[4]={1,-1,0,0};
const int yy[4]={0,0,1,-1};
int inline in(){
	int x=0,c;
	for(;(uint)((c=getchar())-'0')>=10;){
		if(c=='-')return -in();
		if(!~c)throw ~0;
	}
	do{
		x=(x<<3)+(x<<1)+(c-'0');
	}while((uint)((c=getchar())-'0')<10);
	return x;
}
int n,m;
string s[16];
deque<pii>tp;
pii head;
char tail;
void dfs(int x,int y,int c){
	if(c==tail-'0')return;
	for(int i=0;i<4;i++){
		int dx=x+xx[i];
		int dy=y+yy[i];
		if(dx<1||dx>n||dy<1||dy>m)continue;
		if(s[dx][dy]-'0'==c+1){
			tp.push_back(mp(dx,dy));
			dfs(dx,dy,c+1);
			return;
		}
	}
}
int d[16][16];
bool vis[16][16];
//map<deque<pii>,bool>vis;
ll cnt=1;
int bfs(){
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			d[i][j]=INF;
		}
	}
	queue<deque<pii> >q;
	vis[tp[0].fi][tp[0].se]=true;
	d[tp[0].fi][tp[0].se]=0;
	q.push(tp);
	while(!q.empty()){
		deque<pii>cur=q.front();
		q.pop();
//		if(cnt%100000==0)cout<<cnt<<endl;
//		cnt++;
		if(s[cur[0].fi][cur[0].se]=='@')return d[cur[0].fi][cur[0].se];
		for(int i=0;i<4;i++){
			int dx=cur[0].fi+xx[i];
			int dy=cur[0].se+yy[i];
			if(dx<1||dx>n||dy<1||dy>m)continue;
			if(s[dx][dy]=='#')continue;

			bool ok=true;
			for(int i=1;i<tail-'0'-1;i++){
				if(dx==cur[i].fi&&dy==cur[i].se){
					ok=false;
					break;
				}
			}
			if(!ok)continue;
			if(vis[dx][dy])continue;
			vis[dx][dy]=true;
			tp=cur;
			tp.pop_back();
			tp.push_front(mp(dx,dy));
//			if(vis[tp])continue;
//			vis[tp]=true;
			d[dx][dy]=d[cur[0].fi][cur[0].se]+1;
			q.push(tp);
		}
	}
	return -1;
}
int main(){
	cin.sync_with_stdio(false);cin.tie(0);
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>s[i];
		s[i]='#'+s[i];
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			if(s[i][j]=='1'){
				head=mp(i,j);
			}
			else if(s[i][j]>='3'&&s[i][j]<='9'){
				tail=max(tail,s[i][j]);
			}
		}
	}
	tp.push_back(head);
	dfs(head.fi,head.se,1);
//	for(int i=0;i<SZ(tp);i++)cout<<tp[i].fi<<' '<<tp[i].se<<endl;
	cout<<bfs()<<endl;
	return 0;
}


#include<bits/stdc++.h>
//#include<iostream>
//#include<cstdio>
//#include<cstring>
//#include<cstdlib>
//#include<cmath>
//#include<algorithm>
//#include<vector>
//#include<queue>
//#include<stack>
//#include<map>
//#include<set>
using namespace std;
#define SC scanf
#define PR printf
#define pb push_back
#define mp make_pair
#define SZ(v) ((int)(v).size())
#define rep(i,n) for(int i=0;i<(n);i++)
#define all(v) (v).begin(),(v).end()
#define fi first
#define se second
#define db double
#define ldb long double
#define uint unsigned
#define ll long long
typedef pair<int,int> pii;
typedef pair<pii,int> ppi;
typedef pair<int,pii> pip;
typedef pair<pii,pii> ppp;
typedef vector<int> vi;
typedef vector<bool> vb;
typedef vector<string> vs;
typedef vector<ll> vl;
typedef vector<vi> vvi;
typedef vector<pii> vii;
typedef map<int,int> mii;
const int INF=0x3f3f3f3f;
const ll LL_INF=0x3f3f3f3f3f3f3f3f;
const int mr[]={1,0,-1,0};
const int mc[]={0,1,0,-1};
int inline nextin(){
	int t;
	if(scanf("%d",&t)!=1)exit(0);
	return t;
}
char a[15][15];
int dp[15][15][(1<<16)];
int in[15][15];
int getdir(int sr, int sc, int tr, int tc){
    for(int o=0;o<4;o++)
        if(sr+mr[o]==tr && sc+mc[o]==tc) return o;
    return -1;
}
struct TPL{int r,c,t;};
int main(){
	int n,m,s=0,tr=0,tc=0,ur[9]={},uc[9]={};
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++) scanf("%s",a[i]);
    for(int i=0;i<n;i++) for(int j=0;j<m;j++){
        if(a[i][j]>='1' && a[i][j]<='9'){
            ur[a[i][j]-'1']=i;
            uc[a[i][j]-'1']=j;
            s=max(s,a[i][j]-'0');
        }
        if(a[i][j]=='@') tr=i,tc=j;
    }
    int sr=ur[0],sc=uc[0],st=0,mask=(1<<(s*2-2))-1,tag=0;
    for(int i=1;i<s;i++)
        st|=getdir(ur[i],uc[i],ur[i-1],uc[i-1])<<(i*2-2);
    queue<TPL> q;
    q.push((TPL){sr,sc,st});
    memset(dp,-1,sizeof(dp));
    dp[sr][sc][st]=0;
    while(q.size()){
        int r=q.front().r;
        int c=q.front().c;
        int t=q.front().t;
        in[r][c]=++tag;
        for(int i=2,dr=r,dc=c,dt=t;i<s;i++){
            int o=(dt&3)^2;
            dr+=mr[o];
            dc+=mc[o];
            dt>>=2;
            in[dr][dc]=tag;
        }
        q.pop();
        for(int o=0;o<4;o++){
            int dr=r+mr[o];
            int dc=c+mc[o];
            int dt=((t<<2)&mask)|o;
            if(dr<0 || dc<0 || dr>=n || dc>=m
            || a[dr][dc]=='#' || in[dr][dc]==tag
            || ~dp[dr][dc][dt]) continue;
            dp[dr][dc][dt]=dp[r][c][t]+1;
            q.push((TPL){dr,dc,dt});
        }
    }
    int ans=INF;
    for(int i=0;i<1<<16;i++)
        if(~dp[tr][tc][i]) ans=min(ans,dp[tr][tc][i]);
    if(ans==INF) ans=-1;
    printf("%d\n",ans);
}


#include<bits/stdc++.h>
//#include<iostream>
//#include<cstdio>
//#include<cstring>
//#include<cstdlib>
//#include<cmath>
//#include<algorithm>
//#include<vector>
//#include<queue>
//#include<stack>
//#include<map>
//#include<set>
using namespace std;
#define SC scanf
#define PR printf
#define pb push_back
#define mp make_pair
#define SZ(v) ((int)(v).size())
#define rep(i,n) for(int i=0;i<(n);i++)
#define all(v) (v).begin(),(v).end()
#define fi first
#define se second
#define db double
#define ldb long double
#define uint unsigned
#define ll long long
typedef pair<int,int> pii;
typedef pair<pii,int> ppi;
typedef pair<int,pii> pip;
typedef pair<pii,pii> ppp;
typedef vector<int> vi;
typedef vector<bool> vb;
typedef vector<string> vs;
typedef vector<ll> vl;
typedef vector<vi> vvi;
typedef vector<pii> vii;
typedef map<int,int> mii;
const int INF=0x3f3f3f3f;
const ll LL_INF=0x3f3f3f3f3f3f3f3f;
const int xx[4]={1,-1,0,0};
const int yy[4]={0,0,1,-1};
int inline in(){
	int x=0,c;
	for(;(uint)((c=getchar())-'0')>=10;){
		if(c=='-')return -in();
		if(!~c)throw ~0;
	}
	do{
		x=(x<<3)+(x<<1)+(c-'0');
	}while((uint)((c=getchar())-'0')<10);
	return x;
}
int n,m;
string s[16];
deque<pii>tp;
pii head;
char tail;
void dfs(int x,int y,int c){
	if(c==tail-'0')return;
	for(int i=0;i<4;i++){
		int dx=x+xx[i];
		int dy=y+yy[i];
		if(dx<1||dx>n||dy<1||dy>m)continue;
		if(s[dx][dy]-'0'==c+1){
			tp.push_back(mp(dx,dy));
			dfs(dx,dy,c+1);
			return;
		}
	}
}
int d[16][16];
bool vis[16][16][16][16][16][16][16][16][16][16];
//map<deque<pii>,bool>vis;
ll cnt=1;
int bfs(){
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			d[i][j]=INF;
		}
	}
	queue<deque<pii> >q;
	vis[tp[0].fi][tp[0].se][tp[1].fi][tp[1].se][tp[2].fi][tp[2].se][tp[3].fi][tp[3].se][tp[4].fi][tp[4].se]=true;
	d[tp[0].fi][tp[0].se]=0;
	q.push(tp);
	while(!q.empty()){
		deque<pii>cur=q.front();
		q.pop();
//		if(cnt%100000==0)cout<<cnt<<endl;
//		cnt++;
		if(s[cur[0].fi][cur[0].se]=='@')return d[cur[0].fi][cur[0].se];
		for(int i=0;i<4;i++){
			int dx=cur[0].fi+xx[i];
			int dy=cur[0].se+yy[i];
			if(dx<1||dx>n||dy<1||dy>m)continue;
			if(s[dx][dy]=='#')continue;

			bool ok=true;
			for(int i=1;i<tail-'0'-1;i++){
				if(dx==cur[i].fi&&dy==cur[i].se){
					ok=false;
					break;
				}
			}
			if(!ok)continue;

			tp=cur;
			tp.pop_back();
			tp.push_front(mp(dx,dy));
//			if(vis[tp])continue;
//			vis[tp]=true;
			if(vis[tp[0].fi][tp[0].se][tp[1].fi][tp[1].se][tp[2].fi][tp[2].se][tp[3].fi][tp[3].se][tp[4].fi][tp[4].se])continue;
			vis[tp[0].fi][tp[0].se][tp[1].fi][tp[1].se][tp[2].fi][tp[2].se][tp[3].fi][tp[3].se][tp[4].fi][tp[4].se]=true;
			d[dx][dy]=d[cur[0].fi][cur[0].se]+1;
			q.push(tp);
		}
	}
	return -1;
}
int main(){
	cin.sync_with_stdio(false);cin.tie(0);
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>s[i];
		s[i]='#'+s[i];
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			if(s[i][j]=='1'){
				head=mp(i,j);
			}
			else if(s[i][j]>='3'&&s[i][j]<='9'){
				tail=max(tail,s[i][j]);
			}
		}
	}
	tp.push_back(head);
	dfs(head.fi,head.se,1);
//	for(int i=0;i<SZ(tp);i++)cout<<tp[i].fi<<' '<<tp[i].se<<endl;
	cout<<bfs()<<endl;
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
int n,m,cnt,dx[4]={1,-1,0,0},dy[4]={0,0,1,-1};
string b[20];
queue<vector<int> >q;
map<vector<int>,int>mp;
bool u[20][20];
void dfs(int x,int y)
{
	if(x<0 || x>=n || y<0 || y>=m || b[x][y]=='#' || u[x][y])
	{
		return;
	}
	u[x][y]=true;
	for(int i=0;i<4;i++)
	{
		dfs(x+dx[i],y+dy[i]);
	}
}
int main()
{
	cin>>n>>m;
	int k;
	vector<int>it;
	for(int i=0;i<n;i++)
	{
		cin>>b[i];
	}
	for(k=0;;k++)
	{
		bool f=false;
		char c='1'+k;
		for(int i=0;i<n;i++)
		{
			for(int j=0;j<m;j++)
			{
				if(b[i][j]==c)
				{
					f=true;
					it.push_back(i);
					it.push_back(j);
				}
			}
		}
		if(!f)
		{
			break;
		}
	}
	cnt=k;
	dfs(it[0],it[1]);
	bool can=false;
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<m;j++)
		{
			if(b[i][j]=='@' && u[i][j])
			{
				can=true;
			}
		}
	}
	if(!can)
	{
		cout<<-1<<endl;
		return 0;
	}
	q.push(it);
	mp[it]=0;
	while(!q.empty())
	{
		vector<int>v=q.front();
		q.pop();
		int d=mp[v];
		for(int i=0;i<4;i++)
		{
			int x=v[0]+dx[i],y=v[1]+dy[i];
			if(x<0 || x>=n || y<0 || y>=m || b[x][y]=='#')
			{
				continue;
			}
			bool bd=false;
			for(int i=0;i<cnt-1;i++)
			{
				if(x==v[2*i] && y==v[2*i+1])
				{
					bd=true;
				}
			}
			if(bd)
			{
				continue;
			}
			if(b[x][y]=='@')
			{
				cout<<d+1<<endl;
				return 0;
			}
			vector<int>w(2*cnt);
			w[0]=x;
			w[1]=y;
			for(int i=0;i<2*cnt-2;i++)
			{
				w[2+i]=v[i];
			}
			if(mp.find(w)==mp.end())
			{
				mp[w]=d+1;
				q.push(w);
			}
		}
	}
	cout<<-1<<endl;
	return 0;
}


#include<bits/stdc++.h>
#define F first
#define S second
#define MP make_pair
using namespace std;
const int dx[4]={1,0,-1,0};
const int dy[4]={0,1,0,-1};
int n,m,sx,sy;
char c[20][20];
int id[20][20];
int main()
{
	cin>>n>>m;
	memset(c,'#',sizeof(c));
	for(int j=0;j<n;j++)
	{
		for(int i=0;i<m;i++)
		{
			cin>>c[j][i];
			if(c[j][i]=='1')
			{
				sx=i;
				sy=j;
			}
		}
	}
	int num=1,sb=0,x=sx,y=sy;
	for(;;)
	{
		bool ok=false;
		c[y][x]='.';
		for(int d=0;d<4;d++)
		{
			int nx=x+dx[d],ny=y+dy[d];
			if(c[nx][ny]=='0'+num+1)
			{
				sb|=d<<((n-1)*2);
				x=nx;
				y=ny;
				num++;
				ok=true;
			}
		}
		if(!ok)
		{
			break;
		}
	}
	map<pair<pair<int,int>,int>,int>mem;
	queue<pair<pair<int,int>,int> >Q;
	Q.push(MP(MP(sx,sy),sb));
	mem[MP(MP(sx,sy),sb)]=0;
	int now=0;
	while(!Q.empty())
	{
		x=Q.front().F.F;
		y=Q.front().F.S;
		int b=Q.front().S,cnt=mem[Q.front()];
		Q.pop();
		if(c[y][x]=='@')
		{
			cout<<cnt<<endl;
			return 0;
		}
		for(int d=0;d<4;d++)
		{
			int nx=x+dx[(d+2)%4],ny=y+dy[(d+2)%4];
			if(c[ny][nx]=='#')
			{
				continue;
			}
			int nb=((b<<2)|d)&((1<<(2*(n-1)))-1),zx=nx,zy=ny;
			now++;
			int i;
			for(i=0;i<num;i++)
			{
				if(id[zy][zx]==now)
				{
					break;
				}
				id[zy][zx]=now;
				int nd=(nb>>(i*2))&3;
				zx+=dx[nd];
				zy+=dy[nd];
			}
			if(i!=num)
			{
				continue;
			}
			pair<pair<int,int>,int>P=MP(MP(nx,ny),nb);
			if(!mem.count(P))
			{
				Q.push(P);
				mem[P]=cnt+1;
			}
		}
	}
	cout<<-1<<endl;
	return 0;
}


#include<iostream>
#include<sstream>
#include<fstream>
#include<string>
#include<vector>
#include<deque>
#include<queue>
#include<stack>
#include<set>
#include<map>
#include<algorithm>
#include<functional>
#include<utility>
#include<bitset>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<cstdio>
#include<bits/stdc++.h>
#define pii pair<int,int>
using namespace std;
const int dx[4]={0,1,0,-1};
const int dy[4]={1,0,-1,0};
int n,m,ex,ey,cnt=1,she[22][22],now;
char c[22][22];
struct st
{
	int mk,nx,ny;
	bool operator<(const st &a)const
	{
		if(mk>a.mk)
		{
			return true;
		}
		return false;
	}
};
queue<st>q;
map<st,int>mp;
int main()
{
	cin>>n>>m;
	memset(c,'#',sizeof(c));
	st t;
	t.mk=0;
	int x,y;
	for(int j=0;j<n;j++)
	{
		for(int i=0;i<m;i++)
		{
			cin>>c[j][i];
			if(c[j][i]=='1')
			{
				x=i;
				y=j;
				t.nx=x;
				t.ny=y;
			}
		}
	}
	while(1)
	{
		bool ok=false;
		c[y][x]='.';
		for(int d=0;d<4;d++)
		{
			int nx=x+dx[d],ny=y+dy[d];
			if((char)c[ny][nx]==(char)('1'+cnt))
			{
				t.mk|=d<<((n-1)*2);
				x=nx;
				y=ny;
				cnt++;
				ok=true;
			}
		}
		if(!ok)
		{
			break;
		}
	}
	q.push(t);
	mp[t]=0;
	while(!q.empty())
	{
		t=q.front();
		q.pop();
		if(c[t.ny][t.nx]=='@')
		{
			cout<<mp[t]<<endl;
			return 0;
		}
		for(int d=0;d<4;d++)
		{
			int x=t.nx+dx[(d+2)%4],y=t.ny+dy[(d+2)%4];
			if(x<0 || y<0)
			{
				continue;
			}
			if(c[y][x]=='#')
			{
				continue;
			}
			int newmk=((t.mk<<2)|d)&((1<<(2*(n-1)))-1),xx=x,yy=y;
			now++;
			int i;
			for(i=0;i<cnt;i++)
			{
				if(she[yy][xx]==now)
				{
					break;
				}
				she[yy][xx]=now;
				int dd=(newmk>>(i*2))&3;
				xx+=dx[dd];
				yy+=dy[dd];
			}
			if(i!=cnt)
			{
				continue;
			}
			st nt;
			nt.mk=newmk;
			nt.nx=x;
			nt.ny=y;
			if(!mp.count(nt))
			{
//			cout<<x<<' '<<y<<endl;
				mp[nt]=mp[t]+1;
				q.push(nt);
			}
		}
	}
	cout<<-1<<endl;
	return 0;
}


#include<bits/stdc++.h>
#define F first
#define S second
#define MP make_pair
using namespace std;
const int dx[4]={1,0,-1,0};
const int dy[4]={0,1,0,-1};
int n,m,sx,sy;
char c[20][20];
int id[20][20];
int main()
{
	cin>>n>>m;
	memset(c,'#',sizeof(c));
	for(int j=0;j<n;j++)
	{
		for(int i=0;i<m;i++)
		{
			cin>>c[j][i];
			if(c[j][i]=='1')
			{
				sx=i;
				sy=j;
			}
		}
	}
	int num=1,sb=0,x=sx,y=sy;
	for(;;)
	{
		bool ok=false;
		c[y][x]='.';
		for(int d=0;d<4;d++)
		{
			int nx=x+dx[d],ny=y+dy[d];
			if(c[nx][ny]=='0'+n+1)
			{
				sb|=d<<((n-1)*2);
				x=nx;
				y=ny;
				num++;
				ok=true;
			}
		}
		if(!ok)
		{
			break;
		}
	}
	map<pair<pair<int,int>,int>,int>mem;
	queue<pair<pair<int,int>,int> >Q;
	Q.push(MP(MP(sx,sy),sb));
	mem[MP(MP(sx,sy),sb)]=0;
	int now=0;
	while(!Q.empty())
	{
		x=Q.front().F.F;
		y=Q.front().F.S;
		int b=Q.front().S,cnt=mem[Q.front()];
		Q.pop();
		if(c[y][x]=='@')
		{
			cout<<cnt<<endl;
			return 0;
		}
		for(int d=0;d<4;d++)
		{
			int nx=x+dx[(d+2)%4],ny=y+dy[(d+2)%4];
			if(c[ny][nx]=='#')
			{
				continue;
			}
			int nb=((b<<2)|d)&((1<<(2*(n-1)))-1),zx=nx,zy=ny;
			now++;
			int i;
			for(i=0;i<num;i++)
			{
				if(id[zy][zx]==now)
				{
					break;
				}
				id[zy][zx]=now;
				int nd=(nb>>(i*2))&3;
				zx+=dx[nd];
				zy+=dy[nd];
			}
			if(i!=num)
			{
				continue;
			}
			pair<pair<int,int>,int>P=MP(MP(nx,ny),nb);
			if(!mem.count(P))
			{
				Q.push(P);
				mem[P]=cnt+1;
			}
		}
	}
	cout<<-1<<endl;
	return 0;
}


#include<bits/stdc++.h>
#define F first
#define S second
#define pii make_pair
using namespace std;
const int dx[4]={1,0,-1,0};
const int dy[4]={0,1,0,-1};
int n,m,sx,sy,she[22][22];
map<pair<pair<int,int>,int>,int>mem;
queue<pair<pair<int,int>,int> >Q;
char c[22][22];
int main()
{
	cin>>n>>m;
	memset(c,'#',sizeof(c));
	for(int j=0;j<n;j++)
	{
		for(int i=0;i<m;i++)
		{
			cin>>c[j][i];
			if(c[j][i]=='1')
			{
				sx=i;
				sy=j;
			}
		}
	}
	int num=1,sb=0,x=sx,y=sy;
	while(1)
	{
		bool ok=false;
		c[y][x]='.';
		for(int d=0;d<4;d++)
		{
			int nx=x+dx[d],ny=y+dy[d];
			if((char)c[ny][nx]==(char)('0'+num+1))
			{
				sb|=d<<((n-1)*2);
				x=nx;
				y=ny;
				num++;
				ok=true;
			}
		}
		if(!ok)
		{
			break;
		}
	}
	Q.push(pii(pii(sx,sy),sb));
	mem[pii(pii(sx,sy),sb)]=0;
	int now=0;
	while(!Q.empty())
	{
		x=Q.front().F.F;
		y=Q.front().F.S;
		int b=Q.front().S,cnt=mem[Q.front()];
		Q.pop();
		if(c[y][x]=='@')
		{
			cout<<cnt<<endl;
			return 0;
		}
		for(int d=0;d<4;d++)
		{
			int nx=x+dx[(d+2)%4],ny=y+dy[(d+2)%4];
			if(c[ny][nx]=='#')
			{
				continue;
			}
			int nb=((b<<2)|d)&((1<<(2*(n-1)))-1),zx=nx,zy=ny;
			now++;
			int i;
			for(i=0;i<num;i++)
			{
				if(she[zy][zx]==now)
				{
					break;
				}
				she[zy][zx]=now;
				int nd=(nb>>(i*2))&3;
				zx+=dx[nd];
				zy+=dy[nd];
			}
			if(i!=num)
			{
				continue;
			}
			pair<pair<int,int>,int>P=pii(pii(nx,ny),nb);
			if(!mem.count(P))
			{
				Q.push(P);
				mem[P]=cnt+1;
			}
		}
	}
	cout<<-1<<endl;
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
int n,m,cnt,dx[4]={1,-1,0,0},dy[4]={0,0,1,-1};
string b[20];
queue<vector<int> >q;
map<vector<int>,int>mp;
bool u[20][20];
void dfs(int x,int y)
{
	if(x<0 || x>=n || y<0 || y>=m || b[x][y]=='#' || u[x][y])
	{
		return;
	}
	u[x][y]=true;
	for(int i=0;i<4;i++)
	{
		dfs(x+dx[i],y+dy[i]);
	}
}
int main()
{
	cin>>n>>m;
	int k;
	vector<int>it;
	for(int i=0;i<n;i++)
	{
		cin>>b[i];
	}
	for(k=0;;k++)
	{
		bool f=false;
		for(int i=0;i<n;i++)
		{
			for(int j=0;j<m;j++)
			{
				if(b[i][j]=='1'+k)
				{
					f=true;
					it.push_back(i);
					it.push_back(j);
				}
			}
		}
		if(!f)
		{
			break;
		}
	}
	cnt=k;
	dfs(it[0],it[1]);
	bool can=false;
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<m;j++)
		{
			if(b[i][j]=='@' && u[i][j])
			{
				can=true;
			}
		}
	}
	if(!can)
	{
		cout<<-1<<endl;
		return 0;
	}
	q.push(it);
	mp[it]=0;
	while(!q.empty())
	{
		vector<int>v=q.front();
		q.pop();
		int d=mp[v];
		for(int i=0;i<4;i++)
		{
			int x=v[0]+dx[i],y=v[1]+dy[i];
			if(x<0 || x>=n || y<0 || y>=m || b[x][y]=='#')
			{
				continue;
			}
			bool bd=false;
			for(int i=0;i<cnt-1;i++)
			{
				if(x==v[2*i] && y==v[2*i+1])
				{
					bd=true;
				}
			}
			if(bd)
			{
				continue;
			}
			if(b[x][y]=='@')
			{
				cout<<d+1<<endl;
				return 0;
			}
			vector<int>w(2*d);
			w[0]=x;
			w[1]=y;
			for(int i=0;i<2*cnt-2;i++)
			{
				w[2+i]=v[i];
			}
			if(mp.find(w)==mp.end())
			{
				mp[w]=d+1;
				q.push(w);
			}
		}
	}
	cout<<-1<<endl;
	return 0;
}


#include<iostream>
#include<sstream>
#include<fstream>
#include<string>
#include<vector>
#include<deque>
#include<queue>
#include<stack>
#include<set>
#include<map>
#include<algorithm>
#include<functional>
#include<utility>
#include<bitset>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<cstdio>
#define pii pair<int,int>
using namespace std;
const int dx[4]={0,1,0,-1};
const int dy[4]={1,0,-1,0};
int n,m,ex,ey,cnt,she[22][22],now;
char c[22][22];
struct st
{
	int mk,nx,ny,sp;
	bool operator<(const st &a)const
	{
		if(sp>a.sp)
		{
			return true;
		}
		return false;
	}
};
queue<st>q;
map<st,int>mp;
int main()
{
	cin>>n>>m;
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<m;j++)
		{
			cin>>c[i][j];
		}
	}
	st t;
	int x,y;
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<m;j++)
		{
			if(c[i][j]=='1')
			{
				x=i;
				y=j;
			}
			if(c[i][j]=='@')
			{
				ex=i;
				ey=j;
			}
		}
	}
	while(1)
	{
		bool ok=false;
		c[x][y]='.';
		for(int d=0;d<4;d++)
		{
			int nx=x+dx[d],ny=y+dy[d];
			if(c[nx][ny]==('1'+cnt))
			{
				t.mk|=d<<((n-1)*2);
				t.nx=nx;
				t.ny=ny;
				cnt++;
				ok=true;
			}
		}
		if(!ok)
		{
			break;
		}
	}
	q.push(t);
	mp[t]=1;
	while(!q.empty())
	{
		t=q.front();
		q.pop();
		if(t.nx==ex && t.ny==ey)
		{
			cout<<t.sp<<endl;
			return 0;
		}
		for(int d=0;d<4;d++)
		{
			int x=t.nx-dx[d],y=t.ny-dy[d];
			if(x<0 || y<0 || x>=n || y>=m)
			{
				continue;
			}
			if(c[x][y]=='#')
			{
				continue;
			}
			int newmk=((t.mk<<2)|d)&(1<<(2*n-2)-1),xx=x,yy=y;
			now++;
			bool ok=true;
			for(int i=0;i<cnt;i++)
			{
				if(she[xx][yy]==now)
				{
					ok=false;
					break;
				}
				she[xx][yy]=now;
				int dd=(newmk>>(i*2))&3;
				xx+=dx[dd];
				yy+=dy[dd];
			}
			if(!ok)
			{
				continue;
			}
			st nt;
			nt.mk=newmk;
			nt.nx=x;
			nt.ny=y;
			nt.sp=t.sp+1;
			if(!mp[nt])
			{
				mp[nt]=1;
				q.push(nt);
			}
		}
	}
	cout<<-1<<endl;
	return 0;
}


#include<bits/stdc++.h>
#define F first
#define S second
#define MP make_pair
using namespace std;
const int dx[4]={1,0,-1,0};
const int dy[4]={0,1,0,-1};
int n,m,sx,sy;
char c[20][20];
int id[20][20];
int main()
{
	cin>>n>>m;
	memset(c,'#',sizeof(c));
	for(int j=0;j<n;j++)
	{
		for(int i=0;i<m;i++)
		{
			cin>>c[j][i];
			if(c[j][i]=='1')
			{
				sx=i;
				sy=j;
			}
		}
	}
	int num=1,sb=0,x=sx,y=sy;
	for(;;)
	{
		bool ok=false;
		c[y][x]='.';
		for(int d=0;d<4;d++)
		{
			int nx=x+dx[d],ny=y+dy[d];
			if(c[ny][nx]=='0'+num+1)
			{
				sb|=d<<((n-1)*2);
				x=nx;
				y=ny;
				num++;
				ok=true;
			}
		}
		if(!ok)
		{
			break;
		}
	}
	map<pair<pair<int,int>,int>,int>mem;
	queue<pair<pair<int,int>,int> >Q;
	Q.push(MP(MP(sx,sy),sb));
	mem[MP(MP(sx,sy),sb)]=0;
	int now=0;
	while(!Q.empty())
	{
		x=Q.front().F.F;
		y=Q.front().F.S;
		int b=Q.front().S,cnt=mem[Q.front()];
		Q.pop();
		if(c[y][x]=='@')
		{
			cout<<cnt<<endl;
			return 0;
		}
		for(int d=0;d<4;d++)
		{
			int nx=x+dx[(d+2)%4],ny=y+dy[(d+2)%4];
			if(c[ny][nx]=='#')
			{
				continue;
			}
			int nb=((b<<2)|d)&((1<<(2*(n-1)))-1),zx=nx,zy=ny;
			now++;
			int i;
			for(i=0;i<num;i++)
			{
				if(id[zy][zx]==now)
				{
					break;
				}
				id[zy][zx]=now;
				int nd=(nb>>(i*2))&3;
				zx+=dx[nd];
				zy+=dy[nd];
			}
			if(i!=num)
			{
				continue;
			}
			pair<pair<int,int>,int>P=MP(MP(nx,ny),nb);
			if(!mem.count(P))
			{
				Q.push(P);
				mem[P]=cnt+1;
			}
		}
	}
	cout<<-1<<endl;
	return 0;
}


#include<iostream>
#include<sstream>
#include<fstream>
#include<string>
#include<vector>
#include<deque>
#include<queue>
#include<stack>
#include<set>
#include<map>
#include<algorithm>
#include<functional>
#include<utility>
#include<bitset>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<cstdio>
#include<bits/stdc++.h>
#define F first
#define S second
#define pii make_pair
using namespace std;
const int dx[4]={1,0,-1,0};
const int dy[4]={0,1,0,-1};
struct st
{
	int x,y,t;
};
int GD(int sx,int sy,int ex,int ey)
{
	for(int d=0;d<4;d++)
	{
		if(sx+dx[d]==ex && sy+dy[d]==ey)
		{
			return d;
		}
	}
	return -1;
}
int n,m,id[22][22],dp[22][22][(1<<16)],a[11],b[11],cnt,ex,ey;
map<pair<pair<int,int>,int>,int>mem;
queue<pair<pair<int,int>,int> >Q;
char c[22][22];
queue<st>q;
int main()
{
	cin>>n>>m;
	memset(dp,-1,sizeof(dp));
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<m;j++)
		{
			cin>>c[i][j];
		}
	}
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<m;j++)
		{
			if(c[i][j]>='1' && c[i][j]<='9')
			{
				a[c[i][j]-'1']=i;
				b[c[i][j]-'1']=j;
				cnt=max(cnt,c[i][j]-'0');
			}
			if(c[i][j]=='@')
			{
				ex=i;
				ey=j;
			}
		}
	}
	int sst=0;
	for(int i=1;i<cnt;i++)
	{
		sst|=GD(a[i],b[i],a[i-1],b[i-1])<<(i*2-2);
	}
	q.push((st){a[0],b[0],sst});
	dp[a[0]][b[0]][sst]=0;
	int now=0;
	while(!q.empty())
	{
		int x=q.front().x,y=q.front().y,t=q.front().t;
		now++;
		id[x][y]=now;
		for(int i=2,xx=x,yy=y,tt=t;i<cnt;i++)
		{
			int d=(tt&3)^2;
			xx+=dx[d];
			yy+=dy[d];
			tt>>=2;
			id[xx][yy]=now;
		}
		q.pop();
		for(int d=0;d<4;d++)
		{
			int xx=x+dx[d],yy=y+dy[d],tt=(((t<<2)|d)&((1<<(cnt*2-2))-1));
			if(xx<0 || yy<0 || xx>=n || yy>=m || c[xx][yy]=='#' || id[xx][yy]==now || dp[xx][yy][tt]!=-1)
			{
				continue;
			}
			dp[xx][yy][tt]=dp[x][y][t]+1;
			q.push((st){xx,yy,tt});
		}
	}
	int ans=1e9;
	for(int i=0;i<(1<<16);i++)
	{
		if(dp[ex][ey][i]!=-1)
		{
			ans=min(ans,dp[ex][ey][i]);
		}
	}
	if(ans==1e9)
	{
		ans=-1;
	}
	cout<<ans<<endl;
	return 0;
}


#include<bits/stdc++.h>
#define F first
#define S second
#define pii make_pair
using namespace std;
const int dx[4]={1,0,-1,0};
const int dy[4]={0,1,0,-1};
int n,m,sx,sy,she[22][22];
map<pair<pair<int,int>,int>,int>mem;
queue<pair<pair<int,int>,int> >Q;
char c[22][22];
int main()
{
	cin>>n>>m;
	memset(c,'#',sizeof(c));
	for(int j=0;j<n;j++)
	{
		for(int i=0;i<m;i++)
		{
			cin>>c[j][i];
			if(c[j][i]=='1')
			{
				sx=i;
				sy=j;
			}
		}
	}
	int num=1,sb=0,x=sx,y=sy;
	while(1)
	{
		bool ok=false;
		c[y][x]='.';
		for(int d=0;d<4;d++)
		{
			int nx=x+dx[d],ny=y+dy[d];
			if((char)c[ny][nx]==(char)('0'+num))
			{
				sb|=d<<((n-1)*2);
				x=nx;
				y=ny;
				num++;
				ok=true;
			}
		}
		if(!ok)
		{
			break;
		}
	}
	Q.push(pii(pii(sx,sy),sb));
	mem[pii(pii(sx,sy),sb)]=0;
	int now=0;
	while(!Q.empty())
	{
		x=Q.front().F.F;
		y=Q.front().F.S;
		int b=Q.front().S,cnt=mem[Q.front()];
		Q.pop();
		if(c[y][x]=='@')
		{
			cout<<cnt<<endl;
			return 0;
		}
		for(int d=0;d<4;d++)
		{
			int nx=x+dx[(d+2)%4],ny=y+dy[(d+2)%4];
			if(c[ny][nx]=='#')
			{
				continue;
			}
			int nb=((b<<2)|d)&((1<<(2*(n-1)))-1),zx=nx,zy=ny;
			now++;
			int i;
			for(i=0;i<num;i++)
			{
				if(she[zy][zx]==now)
				{
					break;
				}
				she[zy][zx]=now;
				int nd=(nb>>(i*2))&3;
				zx+=dx[nd];
				zy+=dy[nd];
			}
			if(i!=num)
			{
				continue;
			}
			pair<pair<int,int>,int>P=pii(pii(nx,ny),nb);
			if(!mem.count(P))
			{
				Q.push(P);
				mem[P]=cnt+1;
			}
		}
	}
	cout<<-1<<endl;
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
const int mr[4]={0,1,0,-1};
const int mc[4]={1,0,-1,0};
struct TPL
{
	int r,c,t;
};
char a[20][20];
int dp[15][15][1<<16],in[20][20];
int GD(int sr,int sc,int tr,int tc)
{
	for(int o=0;o<4;o++)
	{
		if(sr+mr[o]==tr && sc+mc[o]==tc)
		{
			return o;
		}
	}
	return -1;
}
int main()
{
	int n,m,s=0,tr=0,tc=0,ur[9],uc[9];
	memset(ur,0,sizeof(ur));
	memset(uc,0,sizeof(uc));
	cin>>n>>m;
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<m;j++)
		{
			cin>>a[i][j];
		}
	}
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<m;j++)
		{
			if(a[i][j]>='1' && a[i][j]<='9')
			{
				ur[a[i][j]-'1']=i;
				uc[a[i][j]-'1']=j;
				s=max(s,a[i][j]-'0');
			}
			if(a[i][j]=='@')
			{
				tr=i;
				tc=j;
			}
		}
	}
	int sr=ur[0],sc=uc[0],st=0,mask=(1<<(s*2-2))-1,tag=0;
	for(int i=1;i<s;i++)
	{
		st|=GD(ur[i],uc[i],ur[i-1],uc[i-1])<<(i*2-2);
	}
	queue<TPL>q;
	q.push((TPL){sr,sc,st});
	memset(dp,-1,sizeof(dp));
	dp[sr][sc][st]=0;
	while(q.size())
	{
		int r=q.front().r,c=q.front().c,t=q.front().t;
		in[r][c]=++tag;
		for(int i=2,dr=r,dc=c,dt=t;i<s;i++)
		{
			int o=(dt&3)^2;
			dr+=mr[o];
			dc+=mc[o];
			dt>>=2;
			in[dr][dc]=tag;
		}
		q.pop();
		for(int o=0;o<4;o++)
		{
			int dr=r+mr[o],dc=c+mc[o],dt=((t<<2)&mask)|o;
			if(dr<0 || dc<0 || dr>=n || dc>=m || a[dr][dc]=='#' || in[dr][dc]==tag || ~dp[dr][dc][dt])
			{
				continue;
			}
			dp[dr][dc][dt]=dp[r][c][t]+1;
			q.push((TPL){dr,dc,dt});
		}
	}
	int ans=1e9;
	for(int i=0;i<(1<<16);i++)
	{
		if(~dp[tr][tc][i])
		{
			ans=min(ans,dp[tr][tc][i]);
		}
	}
	if(ans==1e9)
	{
		ans=-1;
	}
	cout<<ans<<endl;
	return 0;
}


#include<bits/stdc++.h>
#define F first
#define S second
#define MP make_pair
using namespace std;
const int dx[4]={1,0,-1,0};
const int dy[4]={0,1,0,-1};
int n,m,sx,sy;
char c[20][20];
int id[20][20];
int main()
{
	cin>>n>>m;
	memset(c,'#',sizeof(c));
	for(int j=0;j<n;j++)
	{
		for(int i=0;i<m;i++)
		{
			cin>>c[j][i];
			if(c[j][i]=='1')
			{
				sx=i;
				sy=j;
			}
		}
	}
	int num=1,sb=0,x=sx,y=sy;
	for(;;)
	{
		bool ok=false;
		c[y][x]='.';
		for(int d=0;d<4;d++)
		{
			int nx=x+dx[d],ny=y+dy[d];
			if((char)c[ny][nx]==(char)('0'+num+1))
			{
				sb|=d<<((n-1)*2);
				x=nx;
				y=ny;
				num++;
				ok=true;
			}
		}
		if(!ok)
		{
			break;
		}
	}
	map<pair<pair<int,int>,int>,int>mem;
	queue<pair<pair<int,int>,int> >Q;
	Q.push(MP(MP(sx,sy),sb));
	mem[MP(MP(sx,sy),sb)]=0;
	int now=0;
	while(!Q.empty())
	{
		x=Q.front().F.F;
		y=Q.front().F.S;
		int b=Q.front().S,cnt=mem[Q.front()];
		Q.pop();
		if(c[y][x]=='@')
		{
			cout<<cnt<<endl;
			return 0;
		}
		for(int d=0;d<4;d++)
		{
			int nx=x+dx[(d+2)%4],ny=y+dy[(d+2)%4];
			if(c[ny][nx]=='#')
			{
				continue;
			}
			int nb=((b<<2)|d)&((1<<(2*(n-1)))-1),zx=nx,zy=ny;
			now++;
			int i;
			for(i=0;i<num;i++)
			{
				if(id[zy][zx]==now)
				{
					break;
				}
				id[zy][zx]=now;
				int nd=(nb>>(i*2))&3;
				zx+=dx[nd];
				zy+=dy[nd];
			}
			if(i!=num)
			{
				continue;
			}
			pair<pair<int,int>,int>P=MP(MP(nx,ny),nb);
			if(!mem.count(P))
			{
				Q.push(P);
				mem[P]=cnt+1;
			}
		}
	}
	cout<<-1<<endl;
	return 0;
}


#include<iostream>
#include<sstream>
#include<fstream>
#include<string>
#include<vector>
#include<deque>
#include<queue>
#include<stack>
#include<set>
#include<map>
#include<algorithm>
#include<functional>
#include<utility>
#include<bitset>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<cstdio>
#define pii pair<int,int>
using namespace std;
const int dx[4]={0,1,0,-1};
const int dy[4]={1,0,-1,0};
int n,m,ex,ey,cnt,she[22][22],now;
char c[22][22];
struct st
{
	int mk,nx,ny,sp;
	bool operator<(const st &a)const
	{
		if(sp>a.sp)
		{
			return true;
		}
		return false;
	}
};
queue<st>q;
map<st,int>mp;
int main()
{
	cin>>n>>m;
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<m;j++)
		{
			cin>>c[i][j];
		}
	}
	st t;
	int x,y;
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<m;j++)
		{
			if(c[i][j]=='1')
			{
				x=i;
				y=j;
			}
			if(c[i][j]=='@')
			{
				ex=i;
				ey=j;
			}
		}
	}
	while(1)
	{
		bool ok=false;
		c[x][y]='.';
		for(int d=0;d<4;d++)
		{
			int nx=x+dx[d],ny=y+dy[d];
			if(c[nx][ny]==('1'+cnt))
			{
				t.mk|=d<<((n-1)*2);
				t.nx=nx;
				t.ny=ny;
				cnt++;
				ok=true;
			}
		}
		if(!ok)
		{
			break;
		}
	}
	q.push(t);
	mp[t]=1;
	while(!q.empty())
	{
		t=q.front();
		q.pop();
		if(t.nx==ex && t.ny==ey)
		{
			cout<<t.sp<<endl;
			return 0;
		}
		for(int d=0;d<4;d++)
		{
			int x=t.nx-dx[d],y=t.ny-dy[d];
			if(c[x][y]=='#')
			{
				continue;
			}
			int newmk=((t.mk<<2)|d)&(1<<(2*n-2)-1),xx=x,yy=y;
			now++;
			bool ok=true;
			for(int i=0;i<cnt;i++)
			{
				if(she[xx][yy]==now)
				{
					ok=false;
					break;
				}
				she[xx][yy]=now;
				int dd=(newmk>>(i*2))&3;
				xx+=dx[dd];
				yy+=dy[dd];
			}
			if(!ok)
			{
				continue;
			}
			st nt;
			nt.mk=newmk;
			nt.nx=x;
			nt.ny=y;
			nt.sp=t.sp+1;
			if(!mp[nt])
			{
				mp[nt]=1;
				q.push(nt);
			}
		}
	}
	cout<<-1<<endl;
	return 0;
}


#include<bits/stdc++.h>
#define F first
#define S second
#define MP make_pair
using namespace std;
const int dx[4]={1,0,-1,0};
const int dy[4]={0,1,0,-1};
int n,m,sx,sy;
char c[20][20];
int id[20][20];
int main()
{
	cin>>n>>m;
	memset(c,'#',sizeof(c));
	for(int j=0;j<n;j++)
	{
		for(int i=0;i<m;i++)
		{
			cin>>c[j][i];
			if(c[j][i]=='1')
			{
				sx=i;
				sy=j;
			}
		}
	}
	int num=1,sb=0,x=sx,y=sy;
	for(;;)
	{
		bool ok=false;
		c[y][x]='.';
		for(int d=0;d<4;d++)
		{
			int nx=x+dx[d],ny=y+dy[d];
			if(c[ny][nx]==(char)('0'+num+1))
			{
				sb|=d<<((n-1)*2);
				x=nx;
				y=ny;
				num++;
				ok=true;
			}
		}
		if(!ok)
		{
			break;
		}
	}
	map<pair<pair<int,int>,int>,int>mem;
	queue<pair<pair<int,int>,int> >Q;
	Q.push(MP(MP(sx,sy),sb));
	mem[MP(MP(sx,sy),sb)]=0;
	int now=0;
	while(!Q.empty())
	{
		x=Q.front().F.F;
		y=Q.front().F.S;
		int b=Q.front().S,cnt=mem[Q.front()];
		Q.pop();
		if(c[y][x]=='@')
		{
			cout<<cnt<<endl;
			return 0;
		}
		for(int d=0;d<4;d++)
		{
			int nx=x+dx[(d+2)%4],ny=y+dy[(d+2)%4];
			if(c[ny][nx]=='#')
			{
				continue;
			}
			int nb=((b<<2)|d)&((1<<(2*(n-1)))-1),zx=nx,zy=ny;
			now++;
			int i;
			for(i=0;i<num;i++)
			{
				if(id[zy][zx]==now)
				{
					break;
				}
				id[zy][zx]=now;
				int nd=(nb>>(i*2))&3;
				zx+=dx[nd];
				zy+=dy[nd];
			}
			if(i!=num)
			{
				continue;
			}
			pair<pair<int,int>,int>P=MP(MP(nx,ny),nb);
			if(!mem.count(P))
			{
				Q.push(P);
				mem[P]=cnt+1;
			}
		}
	}
	cout<<-1<<endl;
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
int dir[4][2]={1,0,0,1,-1,0,0,-1};
int n,m;
char g[20][20];
struct node {
	int x[10],y[10];
	int num;
}s;
int terx,tery;
int len;
queue<node> Q;
int sx,sy;
bool vis[20000000];
int find_relative_dir(int a,int b,node s)
{
	for(int i=0;i<4;i++)
	{
         int x=s.x[b]+dir[i][0];
		 int y=s.y[b]+dir[i][1];
		 if(x==s.x[a] && y==s.y[a]) return i;
	}
}
int gethash(int sx,int sy,node s)
{
	int hash=sx*m+sy;
	for(int i=1;i<len;i++)
	{
		hash=hash*4+find_relative_dir(i,i-1,s);
	}
	return hash;
}
void print(node s)
{
	for(int i=0;i<len;i++)
	{
		printf("(%d %d)\n",s.x[i],s.y[i]);
	}
}
bool qiu_1A()
{

	while(!Q.empty())
	{
		node f=Q.front();Q.pop();
		int x=f.x[0],y=f.y[0];
		for(int i=0;i<4;i++)
		{
            int tx=x+dir[i][0];
			int ty=y+dir[i][1];
			node tm;
			tm.x[0]=tx;
			tm.y[0]=ty;
			if(tx < 1 || ty < 1 || tx > n || ty > m || g[tx][ty]=='#') continue;
			bool flag=false;
			for(int j=1;j<len-1;j++)  if(tx == f.x[j] && ty == f.y[j]) {flag=true;break;}
			if(flag) continue;
			for(int j=1;j<len;j++)
			{
				tm.x[j]=f.x[j-1];
				tm.y[j]=f.y[j-1];
			}
			int hash=gethash(tx,ty,tm);
			if(!vis[hash])
			{
				vis[hash] = true;
				tm.num = f.num+1;
				Q.push(tm);
			}
			if(tx == terx && ty == tery) return printf("%d\n",tm.num),true;
		}
	}
	return printf("-1\n"),true;
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)  scanf("%s",g[i]+1);
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			if(g[i][j]=='@')
			{
				terx=i;
				tery=j;
			}
			if(g[i][j] >= '1' && g[i][j] <='9')
			{
				if(g[i][j]=='1') sx=i,sy=j;
                s.x[g[i][j]-'1']=i;
				s.y[g[i][j]-'1']=j;
				len++;
				g[i][j]='.';
			}
		}
	}
    int hash=gethash(sx,sy,s);
	vis[hash]=true;s.num=0;
	Q.push(s);
	qiu_1A();
	return 0;
}


#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<iostream>
#include<set>
#include<queue>
using namespace std;
typedef __int64  LL;

#define mst(a) memset(a,0,sizeof(a));
#define bug(a) ;//cout<<#a<<" = "<<a<<endl;
#define pos    ;// getchar();
#define isc(a) int a;scanf("%d",&a);
#define sc(a)  scanf("%d",&a);
#define pr(a)  cout<<a<<endl;

char mp[20][20];
int ans = 99999;
struct node{
    int x,y,fs;
    int t;
    int v;
    node(int xx,int yy,int ffs,int tt,int vv){
        x = xx;y = yy; fs = ffs;
        t = tt;
        v = vv;
    }
    node(){}
    bool operator <(const node &p)const{
        return v>p.v;
    }
};
int n,m;
int l;
int tx,ty;
int vis[20][20][65538];
priority_queue<node>fuck;
char fp[20][20];
int ttx,tty;
void lock(node f){
    int d = 49;
    bug(f.x);bug(f.y);
    fp[f.x][f.y]=d;

    int lc = f.fs;
    bug(lc);
    bug(l);
    for(int i = l-2 ; i >=0 ; i --)
    {
        int fc = lc>>(2*i);
        fc = fc&3;
        bug(fc);
        if(fc == 0){
            f.x++;
        }else if(fc == 1){
            f.x--;
        }else if(fc == 2){
            f.y++;
        }else if(fc == 3){
            f.y--;
        }
        fp[f.x][f.y]=++d;
    }
}
void fuck_clear(node f){
    int d = '.';
    bug(f.x);bug(f.y);
    fp[f.x][f.y]=d;

    int lc = f.fs;
    bug(lc);
    bug(l);
    for(int i = l-2 ; i >=0 ; i --)
    {
        int fc = lc>>(2*i);
        fc = fc&3;
        bug(fc);
        if(fc == 0){
            f.x++;
        }else if(fc == 1){
            f.x--;
        }else if(fc == 2){
            f.y++;
        }else if(fc == 3){
            f.y--;
        }
        fp[f.x][f.y]=d;
    }
}

void key(int x,int y,int num,int &id,int step){

    if(step == l)return ;
    id= id<<2;
    bug(id);
    if(fp[x+1][y]==num){
        id=id|0;
        key(x+1,y,num+1,id,step+1);
    }else if(fp[x-1][y]==num){
        id=id|1;
        key(x-1,y,num+1,id,step+1);
    }else if(fp[x][y+1]==num){
        id=id|2;
        key(x,y+1,num+1,id,step+1);
    }else if(fp[x][y-1]==num){
        id=id|3;
        key(x,y-1,num+1,id,step+1);
    }
    return ;
}
void print(){
    return ;
    for(int i = 1 ; i <= n ; i ++){
        for(int j = 1 ; j <= m ; j ++){
            printf("%c",fp[i][j]);
        }
        cout<<endl;
    }
    cout<<endl;
    getchar();
}
int fx[5]={-1,0,1,0};
int fy[5]={0,-1,0,1};
int dd[5]={0,2,1,3};
int bfs(){
    for(int i = 1 ; i<= n ; i ++ ){
        for(int j = 1 ; j <= m ; j ++){
            fp[i][j]=mp[i][j];
        }
    }
    while(!fuck.empty()){
        pos;
        node fc = fuck.top();
        pr(fc.t);
        vis[fc.x][fc.y][fc.fs]=1;
        fuck.pop();
        if(fc.t>=ans)continue;
        bug("fcuk");
        lock(fc);
        print();

        for(int i = 0 ; i < 4 ; i ++){
            int s = fc.x+fx[i];
            int t = fc.y+fy[i];
            if(fp[s][t]=='@'){
                ans = fc.t+1;
            }
            bug(s);
            bug(t);
            if(fp[s][t]=='.'||fp[s][t]=='0'+l){
                int d = fc.fs>>2;
                bug(d);
                int fff = dd[i]<<((2*l-4));
                bug(fff);
                d=d|(fff);
                bug(d);
                if(vis[s][t][d]==0){
                    fuck.push(node(s,t,d,fc.t+1,abs(s-tx)+abs(t-ty)));
                    bug(fuck.size());
                }
            }
        }
        fuck_clear(fc);
        print();
    }
    if(ans<1000)return ans;
    return -1;
}

void init(){
    mst(fp);
    mst(mp);
    mst(vis);
    sc(n);sc(m);
    for(int i = 1 ; i <= n ; i++)scanf("%s",fp[i]+1);
    node fc ;
    l = 0;
    for(int i = 1 ; i <= n ; i++){
        for(int j = 1 ; j <= m ; j ++){
            if(fp[i][j]=='1'){
                fc.x=i;
                fc.y=j;
            }
            if(fp[i][j]=='@'){
                tx = i;
                ty = j;
            }
            if(fp[i][j]<='9'&&fp[i][j]>='1')l++;
        }
    }

    fc.fs = 0 ;
    fc.t = 0;
    fc.v = abs(fc.x-tx)+abs(fc.y-ty);
    key(fc.x,fc.y,'2',fc.fs,1);
    fuck.push(fc);

    for(int i = 1 ; i <= n ; i++){
        for(int j = 1 ; j <= m ; j ++){
            if(fp[i][j]=='#'||fp[i][j]=='@')mp[i][j]=fp[i][j];
            else mp[i][j]='.';
        }
    }
}

int main(){
    init();
    pr(bfs());
}


#include<iostream>
#include<fstream>
#include <vector>
#include <stack>
#include <string>
#include <queue>
#include <set>
#include <algorithm>
#include <cmath>
#include <iostream>
#include <random>
#include <map>
#include <bitset>
#include <iomanip>
#include <numeric>
#define forn(i, n) for (int i = 0; i < (n); i++)
#define forx(i,x,n) for (int i = x; i < (n); i++)
#define form(i, n) for (int i = n-1; i>=0; i--)
#define all(x) (x).begin(), (x).end()
#define sz(a) int(a.size())
#define vi vector<int>
#define vl vector<long long>
#define pb push_back
#define mp make_pair
#define ll long long
#define srt(a) sort(a.begin(), a.end());
#define fi first
#define pl pair<long long,long long>
#define pi pair<int,int>
#define se second
	using namespace std;
const ll N = 1e6;
const ll md = 1e9 + 7;
const int inf = 1e9;
const double e = 1e-18;

int main()
{
	//ifstream cin("input.txt");
	//ofstream cout("output.txt");
	ll q, n, m, r = 0, k, w, i, j, jj, p;
	cin >> n >> m >> q; vector<string> s(n);
	forn(i, n) cin >> s[i];
	queue<pi> qq;
	vector<vi> ans(n, vi(m, inf));
	forn(i, n) forn(j, m) {
		if (i > 0 && s[i - 1][j] == s[i][j]) ans[i][j] = 0;
		if (i < n - 1 && s[i + 1][j] == s[i][j]) ans[i][j] = 0;
		if (j > 0 && s[i][j - 1] == s[i][j]) ans[i][j] = 0;
		if (j < m - 1 && s[i][j + 1] == s[i][j]) ans[i][j] = 0;
		if (ans[i][j] == 0) {
			if (i > 0 && s[i - 1][j] != s[i][j] ) qq.push(mp(i - 1, j));
			if (i < n - 1 && s[i + 1][j] != s[i][j]) qq.push(mp(i + 1, j));
			if (j > 0 && s[i][j - 1] != s[i][j]) qq.push(mp(i, j - 1));
			if (j < m - 1 && s[i][j + 1] != s[i][j]) qq.push(mp(i, j + 1));
		}
	}
	while (sz(qq) != 0) {
		i = qq.front().fi; j = qq.front().second; qq.pop();
		if (i > 0) ans[i][j] = min(ans[i][j], ans[i - 1][j] + 1);
		if (i < n - 1) ans[i][j] = min(ans[i][j], ans[i + 1][j] + 1);
		if (j > 0) ans[i][j] = min(ans[i][j], ans[i][j - 1] + 1);
		if (j < m - 1) ans[i][j] = min(ans[i][j], ans[i][j + 1] + 1);

		if (i > 0 && ans[i - 1][j] > ans[i][j] + 1) { ans[i - 1][j] = ans[i][j] + 1; qq.push(mp(i - 1, j)); }
		if (i < n - 1 && ans[i + 1][j] > ans[i][j] + 1) { ans[i + 1][j] = ans[i][j] + 1; qq.push(mp(i + 1, j)); }
		if (j > 0 && ans[i][j - 1] > ans[i][j] + 1) { ans[i][j - 1] = ans[i][j] + 1; qq.push(mp(i, j - 1)); }
		if (j < m - 1 && ans[i][j + 1] > ans[i][j] + 1) { ans[i][j + 1] = ans[i][j] + 1; qq.push(mp(i, j + 1)); }
	}
	forn(jj, q) {
		cin >> i >> j >> p; i--; j--;
		p -= ans[i][j];
		if (p <= 0 || ans[i][j]==inf) cout << s[i][j] << '\n';
		else {
			if (s[i][j] == '0') {
				if (p % 2 == 0) cout << '0' << '\n';
				else cout << '1' << '\n';
			}
			else {
				if (p % 2 == 0) cout << '1' << '\n';
				else cout << '0' << '\n';
			}
		}

	}

}
namespace {
	auto fast_io = [] {
		std::ios_base::sync_with_stdio(false);
		std::cin.tie(nullptr);
		return 0;
	}();
}


using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace Codeforces.R1350.E
{
    public static class Solver
    {
        public static void Main()
        {
            using (var sw = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false })
            {
                Solve(Console.In, sw);
            }
        }

        public static void Solve(TextReader tr, TextWriter tw)
        {
            WriteAnswer(tw, Parse(tr));
        }

        private static void WriteAnswer(TextWriter tw, string[] answers)
        {
            foreach (var answer in answers)
            {
                tw.WriteLine(answer);
            }
        }

        private static string[] Parse(TextReader tr)
        {
            var nmt = tr.ReadLine().Split().Select(x => int.Parse(x)).ToArray();
            var board = new string[nmt[0]];

            for (int i = 0; i < board.Length; ++i)
            {
                board[i] = tr.ReadLine();
            }

            var p = new long[nmt[2]][];

            for (int i = 0; i < p.Length; ++i)
                p[i] = tr.ReadLine().Split().Select(x => long.Parse(x)).ToArray();

            return Calc(board, p);
        }

        public static string[] Calc(string[] board, long[][] p)
        {
            var n = board.Length;
            var m = board[0].Length;
            var t = p.Length;
            var good = new bool[n, m];

            for (int r = 0; r < n; ++r)
            {
                for (int c = 0; c < m; ++c)
                {
                    if (c + 1 < m && board[r][c + 1] == board[r][c])
                        good[r, c] = true;
                    if (c - 1 >= 0 && board[r][c - 1] == board[r][c])
                        good[r, c] = true;
                    if (r + 1 < n && board[r + 1][c] == board[r][c])
                        good[r, c] = true;
                    if (r - 1 >= 0 && board[r - 1][c] == board[r][c])
                        good[r, c] = true;
                }
            }

            var highValue = int.MaxValue - 1;
            var distanceField = Enumerable.Range(0, n).Select(_ => Enumerable.Repeat(highValue, m).ToArray()).ToArray();
            Bfs(good, distanceField);
            var res = new string[t];

            for (int i = 0; i < t; ++i)
            {
                var r = (int)p[i][0] - 1;
                var c = (int)p[i][1] - 1;
                var iteration = p[i][2];

                var distance = distanceField[r][c];

                if (iteration <= distance)
                {
                    res[i] = board[r][c].ToString();
                }
                else
                {
                    res[i] = (distance - iteration) % 2 == 0 ? board[r][c] == '0' ? "0" : "1" : board[r][c] == '0' ? "1" : "0";
                }
            }

            return res;
        }

        private static void Bfs(bool[,] good, int[][] distanceField)
        {
            var n = good.GetLength(0);
            var m = good.GetLength(1);

            var queue = new Queue<(int, int)>();
            for (int r = 0; r < n; ++r)
            {
                for (int c = 0; c < m; ++ c)
                {
                    if (good[r, c])
                    {
                        distanceField[r][c] = 0;
                        queue.Enqueue((r, c));
                    }
                }
            }

            var highValue = int.MaxValue - 1;

            while (queue.Any())
            {
                var rc = queue.Dequeue();
                var r = rc.Item1;
                var c = rc.Item2;

                if (c - 1 >= 0 && distanceField[r][c - 1] == highValue)
                {
                    distanceField[r][c - 1] = distanceField[r][c] + 1;
                    queue.Enqueue((r, c - 1));
                }

                if (c + 1 < m && distanceField[r][c + 1] == highValue)
                {
                    distanceField[r][c + 1] = distanceField[r][c] + 1;
                    queue.Enqueue((r, c + 1));
                }

                if (r - 1 >= 0 && distanceField[r - 1][c] == highValue)
                {
                    distanceField[r - 1][c] = distanceField[r][c] + 1;
                    queue.Enqueue((r - 1, c));
                }

                if (r + 1 < n && distanceField[r + 1][c] == highValue)
                {
                    distanceField[r + 1][c] = distanceField[r][c] + 1;
                    queue.Enqueue((r + 1, c));
                }
            }
        }
    }
}


using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace Codeforces.R1350.E
{
    public static class Solver
    {
        public static void Main()
        {
            using (var sw = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false })
            {
                Solve(Console.In, sw);
            }
        }

        public static void Solve(TextReader tr, TextWriter tw)
        {
            WriteAnswer(tw, Parse(tr));
        }

        private static void WriteAnswer(TextWriter tw, string[] answers)
        {
            foreach (var answer in answers)
            {
                tw.WriteLine(answer);
            }
        }

        private static string[] Parse(TextReader tr)
        {
            var nmt = tr.ReadLine().Split().Select(x => int.Parse(x)).ToArray();
            var board = new string[nmt[0]];

            for (int i = 0; i < board.Length; ++i)
            {
                board[i] = tr.ReadLine();
            }

            var p = new long[nmt[2]][];

            for (int i = 0; i < p.Length; ++i)
                p[i] = tr.ReadLine().Split().Select(x => long.Parse(x)).ToArray();

            return Calc(board, p);
        }

        public static string[] Calc(string[] board, long[][] p)
        {
            var n = board.Length;
            var m = board[0].Length;
            var t = p.Length;
            var good = new bool[n, m];

            for (int r = 0; r < n; ++r)
            {
                for (int c = 0; c < m; ++c)
                {
                    if (c + 1 < m && board[r][c + 1] == board[r][c])
                        good[r, c] = true;
                    if (c - 1 >= 0 && board[r][c - 1] == board[r][c])
                        good[r, c] = true;
                    if (r + 1 < n && board[r + 1][c] == board[r][c])
                        good[r, c] = true;
                    if (r - 1 >= 0 && board[r - 1][c] == board[r][c])
                        good[r, c] = true;
                }
            }

            var numBad = good.Cast<bool>().Count(x => !x);
            var res = new string[t];

            if (numBad == n * m)
            {
                for (int i = 0; i < t; ++i)
                {
                    var r = p[i][0] - 1;
                    var c = (int)p[i][1] - 1;

                    res[i] = board[r][c].ToString();
                }

                return res;
            }

            var distanceMap = new Dictionary<(int, int), int>();

            for (int i = 0; i < t; ++i)
            {
                var r = (int)p[i][0] - 1;
                var c = (int)p[i][1] - 1;
                var iteration = p[i][2];

                var distance = distanceMap.ContainsKey((r, c)) ? distanceMap[(r, c)]
                    : distanceMap[(r, c)] = Bfs(r, c, good);

                if (iteration <= distance)
                {
                    res[i] = board[r][c].ToString();
                }
                else
                {
                    res[i] = (distance - iteration) % 2 == 0 ? board[r][c] == '0' ? "0" : "1" : board[r][c] == '0' ? "1" : "0";
                }
            }

            return res;
        }

        private static int Bfs(int startR, int startC, bool[,] good)
        {
            var n = good.GetLength(0);
            var m = good.GetLength(1);
            var highValue = int.MaxValue >> 1;

            var distanceField = Enumerable.Range(0, n).Select(_ => Enumerable.Repeat(highValue, m).ToArray()).ToArray();

            distanceField[startR][startC] = 0;

            var queue = new Queue<(int, int)>();
            queue.Enqueue((startR, startC));

            while (queue.Any())
            {
                var rc = queue.Dequeue();
                var r = rc.Item1;
                var c = rc.Item2;

                if (good[r, c])
                    return distanceField[r][c];

                if (c - 1 >= 0 && distanceField[r][c - 1] == highValue)
                {
                    distanceField[r][c - 1] = distanceField[r][c] + 1;
                    queue.Enqueue((r, c - 1));
                }

                if (c + 1 < m && distanceField[r][c + 1] == highValue)
                {
                    distanceField[r][c + 1] = distanceField[r][c] + 1;
                    queue.Enqueue((r, c + 1));
                }

                if (r - 1 >= 0 && distanceField[r - 1][c] == highValue)
                {
                    distanceField[r - 1][c] = distanceField[r][c] + 1;
                    queue.Enqueue((r - 1, c));
                }

                if (r + 1 < n && distanceField[r + 1][c] == highValue)
                {
                    distanceField[r + 1][c] = distanceField[r][c] + 1;
                    queue.Enqueue((r + 1, c));
                }
            }

            return highValue;
        }
    }
}


using System;
using System.IO;
using System.Linq;

namespace Codeforces.R1350.E
{
    public static class Solver
    {
        public static void Main()
        {
            using (var sw = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false })
            {
                Solve(Console.In, sw);
            }
        }

        public static void Solve(TextReader tr, TextWriter tw)
        {
            WriteAnswer(tw, Parse(tr));
        }

        private static void WriteAnswer(TextWriter tw, string[] answers)
        {
            foreach (var answer in answers)
            {
                tw.WriteLine(answer);
            }
        }

        private static string[] Parse(TextReader tr)
        {
            var nmt = tr.ReadLine().Split().Select(x => int.Parse(x)).ToArray();
            var board = new string[nmt[0]];

            for (int i = 0; i < board.Length; ++i)
            {
                board[i] = tr.ReadLine();
            }

            var p = new long[nmt[2]][];

            for (int i = 0; i < p.Length; ++i)
                p[i] = tr.ReadLine().Split().Select(x => long.Parse(x)).ToArray();

            return Calc(board, p);
        }

        public static string[] Calc(string[] board, long[][] p)
        {
            var n = board.Length;
            var m = board[0].Length;
            var t = p.Length;
            var good = new bool[n, m];

            for (int r = 0; r < n; ++r)
            {
                for (int c = 0; c < m; ++c)
                {
                    if (c + 1 < m && board[r][c + 1] == board[r][c])
                        good[r, c] = true;
                    if (c - 1 >= 0 && board[r][c - 1] == board[r][c])
                        good[r, c] = true;
                    if (r + 1 < n && board[r + 1][c] == board[r][c])
                        good[r, c] = true;
                    if (r - 1 >= 0 && board[r - 1][c] == board[r][c])
                        good[r, c] = true;
                }
            }

            var distanceField = new int[n, m];

            for (int r = 0; r < n; ++r)
            {
                for (int c = 0; c < m; ++c)
                {
                    if (!good[r, c])
                    {
                        distanceField[r, c] = int.MaxValue >> 1;
                    }
                }
            }

            var numBad = good.Cast<bool>().Count(x => !x);
            var res = new string[t];

            if (numBad == n * m)
            {
                for (int i = 0; i < t; ++i)
                {
                    var r = p[i][0] - 1;
                    var c = (int)p[i][1] - 1;

                    res[i] = board[r][c].ToString();
                }

                return res;
            }

            while (numBad > 0)
            {
                for (int r = 0; r < n; ++ r)
                {
                    for (int c = 0; c < m; ++c)
                    {
                        var prev = distanceField[r, c];

                        if (c - 1 >= 0)
                            distanceField[r, c] = Math.Min(distanceField[r, c], distanceField[r, c - 1] + 1);
                        if (c + 1 < m)
                            distanceField[r, c] = Math.Min(distanceField[r, c], distanceField[r, c + 1] + 1);
                        if (r - 1 >= 0)
                            distanceField[r, c] = Math.Min(distanceField[r, c], distanceField[r - 1, c] + 1);
                        if (r + 1 < n)
                            distanceField[r, c] = Math.Min(distanceField[r, c], distanceField[r + 1, c] + 1);

                        if (prev == (int.MaxValue >> 1) && distanceField[r, c] < (int.MaxValue >> 1))
                            --numBad;
                    }
                }
            }

            for (int i = 0; i < t; ++i)
            {
                var r = p[i][0] - 1;
                var c = (int)p[i][1] - 1;
                var iteration = p[i][2];

                if (iteration <= distanceField[r, c])
                {
                    res[i] = board[r][c].ToString();
                }
                else
                {
                    res[i] = (distanceField[r, c] - iteration) % 2 == 0 ? board[r][c] == '0' ? "0" : "1" : board[r][c] == '0' ? "1" : "0";
                }
            }

            return res;
        }
    }
}


using System;
using System.IO;
using System.Linq;

namespace Codeforces.R1350.E
{
    public static class Solver
    {
        public static void Main()
        {
            using (var sw = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false })
            {
                Solve(Console.In, sw);
            }
        }

        public static void Solve(TextReader tr, TextWriter tw)
        {
            WriteAnswer(tw, Parse(tr));
        }

        private static void WriteAnswer(TextWriter tw, string[] answers)
        {
            foreach (var answer in answers)
            {
                tw.WriteLine(answer);
            }
        }

        private static string[] Parse(TextReader tr)
        {
            var nmt = tr.ReadLine().Split().Select(x => int.Parse(x)).ToArray();
            var board = new string[nmt[0]];

            for (int i = 0; i < board.Length; ++i)
            {
                board[i] = tr.ReadLine();
            }

            var p = new long[nmt[2]][];

            for (int i = 0; i < p.Length; ++i)
                p[i] = tr.ReadLine().Split().Select(x => long.Parse(x)).ToArray();

            return Calc(board, p);
        }

        public static string[] Calc(string[] board, long[][] p)
        {
            var n = board.Length;
            var m = board[0].Length;
            var t = p.Length;
            var good = new bool[n, m];

            for (int r = 0; r < n; ++r)
            {
                for (int c = 0; c < m; ++c)
                {
                    if (c + 1 < m && board[r][c + 1] == board[r][c])
                        good[r, c] = true;
                    if (c - 1 >= 0 && board[r][c - 1] == board[r][c])
                        good[r, c] = true;
                    if (r + 1 < n && board[r + 1][c] == board[r][c])
                        good[r, c] = true;
                    if (r - 1 >= 0 && board[r - 1][c] == board[r][c])
                        good[r, c] = true;
                }
            }

            var distanceField = new int[n, m];

            for (int r = 0; r < n; ++r)
            {
                for (int c = 0; c < m; ++c)
                {
                    if (!good[r, c])
                    {
                        distanceField[r, c] = int.MaxValue >> 1;
                    }
                }
            }

            var numBad = good.Cast<bool>().Count(x => !x);
            var res = new string[t];

            if (numBad == n * m)
            {
                for (int i = 0; i < t; ++i)
                {
                    var r = p[i][0] - 1;
                    var c = (int)p[i][1] - 1;

                    res[i] = board[r][c].ToString();
                }

                return res;
            }

            for (var updated = true; updated;)
            {
                updated = false;

                for (int r = 0; r < n; ++ r)
                {
                    for (int c = 0; c < m; ++c)
                    {
                        var prev = distanceField[r, c];

                        if (c - 1 >= 0)
                            distanceField[r, c] = Math.Min(distanceField[r, c], distanceField[r, c - 1] + 1);
                        if (c + 1 < m)
                            distanceField[r, c] = Math.Min(distanceField[r, c], distanceField[r, c + 1] + 1);
                        if (r - 1 >= 0)
                            distanceField[r, c] = Math.Min(distanceField[r, c], distanceField[r - 1, c] + 1);
                        if (r + 1 < n)
                            distanceField[r, c] = Math.Min(distanceField[r, c], distanceField[r + 1, c] + 1);

                        if (prev != distanceField[r, c])
                            updated = true;
                    }
                }
            }

            for (int i = 0; i < t; ++i)
            {
                var r = p[i][0] - 1;
                var c = (int)p[i][1] - 1;
                var iteration = p[i][2];

                if (iteration <= distanceField[r, c])
                {
                    res[i] = board[r][c].ToString();
                }
                else
                {
                    res[i] = (distanceField[r, c] - iteration) % 2 == 0 ? board[r][c] == '0' ? "0" : "1" : board[r][c] == '0' ? "1" : "0";
                }
            }

            return res;
        }
    }
}


using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace Codeforces.R1350.E
{
    public static class Solver
    {
        public static void Main()
        {
            using (var sw = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false })
            {
                Solve(Console.In, sw);
            }
        }

        public static void Solve(TextReader tr, TextWriter tw)
        {
            WriteAnswer(tw, Parse(tr));
        }

        private static void WriteAnswer(TextWriter tw, string[] answers)
        {
            foreach (var answer in answers)
            {
                tw.WriteLine(answer);
            }
        }

        private static string[] Parse(TextReader tr)
        {
            var nmt = tr.ReadLine().Split().Select(x => int.Parse(x)).ToArray();
            var board = new string[nmt[0]];

            for (int i = 0; i < board.Length; ++i)
            {
                board[i] = tr.ReadLine();
            }

            var p = new long[nmt[2]][];

            for (int i = 0; i < p.Length; ++i)
                p[i] = tr.ReadLine().Split().Select(x => long.Parse(x)).ToArray();

            return Calc(board, p);
        }

        public static string[] Calc(string[] board, long[][] p)
        {
            var n = board.Length;
            var m = board[0].Length;
            var t = p.Length;
            var good = new bool[n, m];

            for (int r = 0; r < n; ++r)
            {
                for (int c = 0; c < m; ++c)
                {
                    if (c + 1 < m && board[r][c + 1] == board[r][c])
                        good[r, c] = true;
                    if (c - 1 >= 0 && board[r][c - 1] == board[r][c])
                        good[r, c] = true;
                    if (r + 1 < n && board[r + 1][c] == board[r][c])
                        good[r, c] = true;
                    if (r - 1 >= 0 && board[r - 1][c] == board[r][c])
                        good[r, c] = true;
                }
            }

            var res = new string[t];

            if (!good.Cast<bool>().Any(x => x))
            {
                for (int i = 0; i < t; ++i)
                {
                    var r = p[i][0] - 1;
                    var c = (int)p[i][1] - 1;

                    res[i] = board[r][c].ToString();
                }

                return res;
            }

            var highValue = int.MaxValue >> 1;
            var distanceField = Enumerable.Range(0, n).Select(_ => Enumerable.Repeat(highValue, m).ToArray()).ToArray();
            Bfs(good, distanceField);

            for (int i = 0; i < t; ++i)
            {
                var r = (int)p[i][0] - 1;
                var c = (int)p[i][1] - 1;
                var iteration = p[i][2];

                var distance = distanceField[r][c];

                if (iteration <= distance)
                {
                    res[i] = board[r][c].ToString();
                }
                else
                {
                    res[i] = (distance - iteration) % 2 == 0 ? board[r][c] == '0' ? "0" : "1" : board[r][c] == '0' ? "1" : "0";
                }
            }

            return res;
        }

        private static void Bfs(bool[,] good, int[][] distanceField)
        {
            var n = good.GetLength(0);
            var m = good.GetLength(1);

            var queue = new Queue<(int, int)>();
            for (int r = 0; r < n; ++r)
            {
                for (int c = 0; c < m; ++ c)
                {
                    if (good[r, c])
                    {
                        distanceField[r][c] = 0;
                        queue.Enqueue((r, c));
                    }
                }
            }

            var highValue = int.MaxValue >> 1;

            while (queue.Any())
            {
                var rc = queue.Dequeue();
                var r = rc.Item1;
                var c = rc.Item2;

                if (c - 1 >= 0 && distanceField[r][c - 1] == highValue)
                {
                    distanceField[r][c - 1] = distanceField[r][c] + 1;
                    queue.Enqueue((r, c - 1));
                }

                if (c + 1 < m && distanceField[r][c + 1] == highValue)
                {
                    distanceField[r][c + 1] = distanceField[r][c] + 1;
                    queue.Enqueue((r, c + 1));
                }

                if (r - 1 >= 0 && distanceField[r - 1][c] == highValue)
                {
                    distanceField[r - 1][c] = distanceField[r][c] + 1;
                    queue.Enqueue((r - 1, c));
                }

                if (r + 1 < n && distanceField[r + 1][c] == highValue)
                {
                    distanceField[r + 1][c] = distanceField[r][c] + 1;
                    queue.Enqueue((r + 1, c));
                }
            }
        }
    }
}


using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace Codeforces.R1350.E
{
    public static class Solver
    {
        public static void Main()
        {
            using (var sw = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false })
            {
                Solve(Console.In, sw);
            }
        }

        public static void Solve(TextReader tr, TextWriter tw)
        {
            WriteAnswer(tw, Parse(tr));
        }

        private static void WriteAnswer(TextWriter tw, string[] answers)
        {
            foreach (var answer in answers)
            {
                tw.WriteLine(answer);
            }
        }

        private static string[] Parse(TextReader tr)
        {
            var nmt = tr.ReadLine().Split().Select(x => int.Parse(x)).ToArray();
            var board = new string[nmt[0]];

            for (int i = 0; i < board.Length; ++i)
            {
                board[i] = tr.ReadLine();
            }

            var p = new long[nmt[2]][];

            for (int i = 0; i < p.Length; ++i)
                p[i] = tr.ReadLine().Split().Select(x => long.Parse(x)).ToArray();

            return Calc(board, p);
        }

        public static string[] Calc(string[] board, long[][] p)
        {
            var n = board.Length;
            var m = board[0].Length;
            var t = p.Length;
            var good = new bool[n, m];

            for (int r = 0; r < n; ++r)
            {
                for (int c = 0; c < m; ++c)
                {
                    if (c + 1 < m && board[r][c + 1] == board[r][c])
                        good[r, c] = true;
                    if (c - 1 >= 0 && board[r][c - 1] == board[r][c])
                        good[r, c] = true;
                    if (r + 1 < n && board[r + 1][c] == board[r][c])
                        good[r, c] = true;
                    if (r - 1 >= 0 && board[r - 1][c] == board[r][c])
                        good[r, c] = true;
                }
            }

            var numBad = good.Cast<bool>().Count(x => !x);
            var res = new string[t];

            if (numBad == n * m)
            {
                for (int i = 0; i < t; ++i)
                {
                    var r = p[i][0] - 1;
                    var c = (int)p[i][1] - 1;

                    res[i] = board[r][c].ToString();
                }

                return res;
            }

            for (int i = 0; i < t; ++i)
            {
                var r = (int)p[i][0] - 1;
                var c = (int)p[i][1] - 1;
                var iteration = p[i][2];

                var distance = Bfs(r, c, good);

                if (iteration <= distance)
                {
                    res[i] = board[r][c].ToString();
                }
                else
                {
                    res[i] = (distance - iteration) % 2 == 0 ? board[r][c] == '0' ? "0" : "1" : board[r][c] == '0' ? "1" : "0";
                }
            }

            return res;
        }

        private static int Bfs(int startR, int startC, bool[,] good)
        {
            var n = good.GetLength(0);
            var m = good.GetLength(1);
            var highValue = int.MaxValue >> 1;

            var distanceField = Enumerable.Range(0, n).Select(_ => Enumerable.Repeat(highValue, m).ToArray()).ToArray();

            distanceField[startR][startC] = 0;

            var queue = new Queue<(int, int)>();
            queue.Enqueue((startR, startC));

            while (queue.Any())
            {
                var rc = queue.Dequeue();
                var r = rc.Item1;
                var c = rc.Item2;

                if (good[r, c])
                    return distanceField[r][c];

                if (c - 1 >= 0 && distanceField[r][c - 1] == highValue)
                {
                    distanceField[r][c - 1] = distanceField[r][c] + 1;
                    queue.Enqueue((r, c - 1));
                }

                if (c + 1 < m && distanceField[r][c + 1] == highValue)
                {
                    distanceField[r][c + 1] = distanceField[r][c] + 1;
                    queue.Enqueue((r, c + 1));
                }

                if (r - 1 >= 0 && distanceField[r - 1][c] == highValue)
                {
                    distanceField[r - 1][c] = distanceField[r][c] + 1;
                    queue.Enqueue((r - 1, c));
                }

                if (r + 1 < n && distanceField[r + 1][c] == highValue)
                {
                    distanceField[r + 1][c] = distanceField[r][c] + 1;
                    queue.Enqueue((r + 1, c));
                }
            }

            return highValue;
        }
    }
}


using System;
using System.IO;
using System.Linq;

namespace Codeforces.R1350.E
{
    public static class Solver
    {
        public static void Main()
        {
            using (var sw = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false })
            {
                Solve(Console.In, sw);
            }
        }

        public static void Solve(TextReader tr, TextWriter tw)
        {
            WriteAnswer(tw, Parse(tr));
        }

        private static void WriteAnswer(TextWriter tw, string[] answers)
        {
            foreach (var answer in answers)
            {
                tw.WriteLine(answer);
            }
        }

        private static string[] Parse(TextReader tr)
        {
            var nmt = tr.ReadLine().Split().Select(x => int.Parse(x)).ToArray();
            var board = new string[nmt[0]];

            for (int i = 0; i < board.Length; ++i)
            {
                board[i] = tr.ReadLine();
            }

            var p = new long[nmt[2]][];

            for (int i = 0; i < p.Length; ++i)
                p[i] = tr.ReadLine().Split().Select(x => long.Parse(x)).ToArray();

            return Calc(board, p);
        }

        public static string[] Calc(string[] board, long[][] p)
        {
            var n = board.Length;
            var m = board[0].Length;
            var t = p.Length;
            var good = new bool[n, m];

            for (int r = 0; r < n; ++r)
            {
                for (int c = 0; c < m; ++c)
                {
                    if (c + 1 < m && board[r][c + 1] == board[r][c])
                        good[r, c] = true;
                    if (c - 1 >= 0 && board[r][c - 1] == board[r][c])
                        good[r, c] = true;
                    if (r + 1 < n && board[r + 1][c] == board[r][c])
                        good[r, c] = true;
                    if (r - 1 >= 0 && board[r - 1][c] == board[r][c])
                        good[r, c] = true;
                }
            }

            var distanceField = new int[n, m];

            for (int r = 0; r < n; ++r)
            {
                for (int c = 0; c < m; ++c)
                {
                    if (!good[r, c])
                    {
                        distanceField[r, c] = int.MaxValue >> 1;
                    }
                }
            }

            var numBad = good.Cast<bool>().Count(x => !x);

            for (int i = 0; i < numBad; ++i)
            {
                for (int r = 0; r < n; ++ r)
                {
                    for (int c = 0; c < m; ++c)
                    {
                        if (c - 1 >= 0)
                            distanceField[r, c] = Math.Min(distanceField[r, c], distanceField[r, c - 1] + 1);
                        if (c + 1 < m)
                            distanceField[r, c] = Math.Min(distanceField[r, c], distanceField[r, c + 1] + 1);
                        if (r - 1 >= 0)
                            distanceField[r, c] = Math.Min(distanceField[r, c], distanceField[r - 1, c] + 1);
                        if (r + 1 < n)
                            distanceField[r, c] = Math.Min(distanceField[r, c], distanceField[r + 1, c] + 1);
                    }
                }
            }

            var res = new string[t];

            for (int i = 0; i < t; ++i)
            {
                var r = p[i][0] - 1;
                var c = (int)p[i][1] - 1;
                var iteration = p[i][2];

                if (iteration <= distanceField[r, c] || distanceField[r, c] == int.MaxValue)
                {
                    res[i] = board[r][c].ToString();
                }
                else
                {
                    res[i] = (distanceField[r, c] - iteration) % 2 == 0 ? board[r][c] == '0' ? "0" : "1" : board[r][c] == '0' ? "1" : "0";
                }
            }

            return res;
        }
    }
}


#![allow(unused_imports, unused_macros, dead_code)]

macro_rules! min {
    (.. $x:expr) => {{
        let mut it = $x.iter();
        it.next().map(|z| it.fold(z, |x, y| min!(x, y)))
    }};
    ($x:expr) => ($x);
    ($x:expr, $($ys:expr),*) => {{
        let t = min!($($ys),*);
        if $x < t { $x } else { t }
    }}
}
macro_rules! max {
    (.. $x:expr) => {{
        let mut it = $x.iter();
        it.next().map(|z| it.fold(z, |x, y| max!(x, y)))
    }};
    ($x:expr) => ($x);
    ($x:expr, $($ys:expr),*) => {{
        let t = max!($($ys),*);
        if $x > t { $x } else { t }
    }}
}
macro_rules! ewriteln {
    ($($args:expr),*) => { let _ = writeln!(&mut std::io::stderr(), $($args),*); };
}
macro_rules! trace {
    ($x:expr) => { ewriteln!(">>> {} = {:?}", stringify!($x), $x) };
    ($($xs:expr),*) => { trace!(($($xs),*)) }
}
macro_rules! put {
    (.. $x:expr) => {{
        let mut it = $x.iter();
        if let Some(x) = it.next() { print!("{}", x); }
        for x in it { print!(" {}", x); }
        println!("");
    }};
    ($x:expr) => { println!("{}", $x) };
    ($x:expr, $($xs:expr),*) => { print!("{} ", $x); put!($($xs),*) }
}

const M: i64 = 998_244_353;

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
struct ModInt(i64, i64); // (residual, modulo)
impl ModInt {
    fn new(residual: i64, modulo: i64) -> ModInt {
        if residual >= modulo {
            ModInt(residual % modulo, modulo)
        } else if residual < 0 {
            ModInt((residual % modulo) + modulo, modulo)
        } else {
            ModInt(residual, modulo)
        }
    }
    fn unwrap(self) -> i64 {
        self.0
    }
    fn inv(self) -> Self {
        fn exgcd(r0: i64, a0: i64, b0: i64, r: i64, a: i64, b: i64) -> (i64, i64, i64) {
            if r > 0 {
                exgcd(r, a, b, r0 % r, a0 - r0 / r * a, b0 - r0 / r * b)
            } else {
                (a0, b0, r0)
            }
        }
        let (a, _, r) = exgcd(self.0, 1, 0, self.1, 0, 1);
        if r != 1 {
            panic!("{:?} has no inverse!", self);
        }
        ModInt(((a % self.1) + self.1) % self.1, self.1)
    }
    fn pow(self, n: i64) -> Self {
        if n < 0 {
            self.pow(-n).inv()
        } else if n == 0 {
            ModInt(1, self.1)
        } else if n == 1 {
            self
        } else {
            let mut x = (self * self).pow(n / 2);
            if n % 2 == 1 {
                x *= self
            }
            x
        }
    }
}
impl std::fmt::Display for ModInt {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "{}", self.0)
    }
}
impl std::ops::Neg for ModInt {
    type Output = Self;
    fn neg(self) -> Self {
        if self.0 == 0 {
            return self;
        }
        ModInt(self.1 - self.0, self.1)
    }
}
impl std::ops::Add<i64> for ModInt {
    type Output = Self;
    fn add(self, other: i64) -> Self {
        ModInt::new(self.0 + other, self.1)
    }
}
impl std::ops::Add for ModInt {
    type Output = Self;
    fn add(self, other: ModInt) -> Self {
        self + other.0
    }
}
impl std::ops::Add<ModInt> for i64 {
    type Output = ModInt;
    fn add(self, other: ModInt) -> ModInt {
        other + self
    }
}
impl std::ops::AddAssign<i64> for ModInt {
    fn add_assign(&mut self, other: i64) {
        self.0 = ModInt::new(self.0 + other, self.1).0;
    }
}
impl std::ops::AddAssign for ModInt {
    fn add_assign(&mut self, other: ModInt) {
        *self += other.0;
    }
}
impl std::ops::Sub<i64> for ModInt {
    type Output = Self;
    fn sub(self, other: i64) -> Self {
        ModInt::new(self.0 - other, self.1)
    }
}
impl std::ops::Sub for ModInt {
    type Output = Self;
    fn sub(self, other: ModInt) -> Self {
        self - other.0
    }
}
impl std::ops::Sub<ModInt> for i64 {
    type Output = ModInt;
    fn sub(self, other: ModInt) -> ModInt {
        ModInt::new(self - other.0, other.1)
    }
}
impl std::ops::SubAssign<i64> for ModInt {
    fn sub_assign(&mut self, other: i64) {
        self.0 = ModInt::new(self.0 - other, self.1).0;
    }
}
impl std::ops::SubAssign for ModInt {
    fn sub_assign(&mut self, other: ModInt) {
        *self -= other.0;
    }
}
impl std::ops::Mul<i64> for ModInt {
    type Output = Self;
    fn mul(self, other: i64) -> Self {
        ModInt::new(self.0 * other, self.1)
    }
}
impl std::ops::Mul for ModInt {
    type Output = Self;
    fn mul(self, other: ModInt) -> Self {
        self * other.0
    }
}
impl std::ops::Mul<ModInt> for i64 {
    type Output = ModInt;
    fn mul(self, other: ModInt) -> ModInt {
        other * self
    }
}
impl std::ops::MulAssign<i64> for ModInt {
    fn mul_assign(&mut self, other: i64) {
        self.0 = ModInt::new(self.0 * other, self.1).0;
    }
}
impl std::ops::MulAssign for ModInt {
    fn mul_assign(&mut self, other: ModInt) {
        *self *= other.0;
    }
}
impl std::ops::Div for ModInt {
    type Output = Self;
    fn div(self, other: ModInt) -> Self {
        self * other.inv()
    }
}
impl std::ops::Div<i64> for ModInt {
    type Output = Self;
    fn div(self, other: i64) -> Self {
        self / ModInt(other, self.1)
    }
}
impl std::ops::Div<ModInt> for i64 {
    type Output = ModInt;
    fn div(self, other: ModInt) -> ModInt {
        other.inv() * self
    }
}
impl std::ops::DivAssign for ModInt {
    fn div_assign(&mut self, other: ModInt) {
        self.0 = (self.clone() / other).0;
    }
}
impl std::ops::DivAssign<i64> for ModInt {
    fn div_assign(&mut self, other: i64) {
        *self /= ModInt(other, self.1);
    }
}

fn main() {
    let mut sc = Scanner::new();
    let n: usize = sc.cin();
    let mut ans = vec![ModInt(1, M)];

    for m in 1..n {
        if ans.len() == 1 {
            ans[0] *= 3;
            ans.push(ModInt(1, M));
        } else {
            let mut xs = vec![ModInt(1, M); m + 1];
            xs[0] = ans[0] * 3 + ans[1];
            for i in 1..m - 1 {
                xs[i] = ans[i - 1] + 4 * ans[i] + ans[i + 1];
            }
            xs[m - 1] = ans[m - 2] + 4 * ans[m - 1];
            ans = xs;
        }
    }

    put!(..ans);
}

use std::collections::VecDeque;
use std::io::{self, Write};
use std::str::FromStr;

struct Scanner {
    stdin: io::Stdin,
    buffer: VecDeque<String>,
}
impl Scanner {
    fn new() -> Self {
        Scanner {
            stdin: io::stdin(),
            buffer: VecDeque::new(),
        }
    }
    fn cin<T: FromStr>(&mut self) -> T {
        while self.buffer.is_empty() {
            let mut line = String::new();
            let _ = self.stdin.read_line(&mut line);
            for w in line.split_whitespace() {
                self.buffer.push_back(String::from(w));
            }
        }
        self.buffer.pop_front().unwrap().parse::<T>().ok().unwrap()
    }
    fn chars(&mut self) -> Vec<char> {
        self.cin::<String>().chars().collect()
    }
    fn vec<T: FromStr>(&mut self, n: usize) -> Vec<T> {
        (0..n).map(|_| self.cin()).collect()
    }
}


#![allow(unused_imports, unused_macros, dead_code)]

macro_rules! min {
    (.. $x:expr) => {{
        let mut it = $x.iter();
        it.next().map(|z| it.fold(z, |x, y| min!(x, y)))
    }};
    ($x:expr) => ($x);
    ($x:expr, $($ys:expr),*) => {{
        let t = min!($($ys),*);
        if $x < t { $x } else { t }
    }}
}
macro_rules! max {
    (.. $x:expr) => {{
        let mut it = $x.iter();
        it.next().map(|z| it.fold(z, |x, y| max!(x, y)))
    }};
    ($x:expr) => ($x);
    ($x:expr, $($ys:expr),*) => {{
        let t = max!($($ys),*);
        if $x > t { $x } else { t }
    }}
}
macro_rules! ewriteln {
    ($($args:expr),*) => { let _ = writeln!(&mut std::io::stderr(), $($args),*); };
}
macro_rules! trace {
    ($x:expr) => { ewriteln!(">>> {} = {:?}", stringify!($x), $x) };
    ($($xs:expr),*) => { trace!(($($xs),*)) }
}
macro_rules! put {
    (.. $x:expr) => {{
        let mut it = $x.iter();
        if let Some(x) = it.next() { print!("{}", x); }
        for x in it { print!(" {}", x); }
        println!("");
    }};
    ($x:expr) => { println!("{}", $x) };
    ($x:expr, $($xs:expr),*) => { print!("{} ", $x); put!($($xs),*) }
}

const M: i64 = 1_000_000_007;

macro_rules! list {
    ($($t:tt)*) => {{ let mut r = vec![]; list_inner!(r, $($t)*); r }}
}
macro_rules! list_inner {
    ($r:expr) => {};
    ($r:expr, $e:expr) => { $r.push($e) };
    ($r:expr, $e:expr;) => { $r.push($e) };
    ($r:expr, $e:expr; for $k:ident in $range:expr) => { for $k in $range { list_inner!($r, $e) } };
    ($r:expr, $e:expr; if $cond:expr) => { if $cond { list_inner!($r, $e) } };
    ($r:expr, $e:expr; for $k:ident in $range:expr ; $($t:tt)*) => { for $k in $range { list_inner!($r, $e ; $($t)*); } };
    ($r:expr, $e:expr; if $cond:expr ; $($t:tt)*) => { if $cond { list_inner!($r, $e ; $($t)*); } };
}

mod neighbor {
    pub struct Grid4(pub usize, pub usize);
    impl Grid4 {
        pub fn iter(&self, i: usize, j: usize) -> NeighborIter<(usize, usize)> {
            NeighborIter::new(list! {
                (i + s - 1, j + t - 1);
                for s in 0..3;
                for t in 0..3;
                if (s + t) % 2 == 1;
                if (1..self.0 + 1).contains(&(i + s));
                if (1..self.1 + 1).contains(&(j + t));
            })
        }
    }
    pub struct Grid8(pub usize, pub usize);
    impl Grid8 {
        pub fn iter<'a>(&'a self, i: usize, j: usize) -> NeighborIter<(usize, usize)> {
            NeighborIter::new(list! {
                (i + s - 1, j + t - 1);
                for s in 0..3;
                for t in 0..3;
                if s * t != 1;
                if (1..self.0 + 1).contains(&(i + s));
                if (1..self.1 + 1).contains(&(j + t));
            })
        }
    }
    pub struct NeighborIter<T>(Vec<T>, usize);
    impl<T> NeighborIter<T> {
        fn new(data: Vec<T>) -> Self {
            NeighborIter(data, 0)
        }
    }
    impl<T: Copy> Iterator for NeighborIter<T> {
        type Item = T;
        fn next(&mut self) -> Option<Self::Item> {
            if self.0.len() > self.1 {
                self.1 += 1;
                Some(self.0[self.1 - 1])
            } else {
                None
            }
        }
    }
}

fn main() {
    let mut sc = Scanner::new();
    let h: usize = sc.cin();
    let w: usize = sc.cin();
    let t: usize = sc.cin();

    let f: Vec<Vec<char>> = (0..h).map(|_| sc.chars()).collect();
    let neigh = neighbor::Grid4(h, w);

    let mut memo: Vec<Vec<u64>> = vec![vec![(h + w) as u64 * 2; w]; h];
    let mut queue = std::collections::BinaryHeap::new();
    let mut ok = false;
    {
        for i in 0..h {
            for j in 0..w {
                for (ni, nj) in neigh.iter(i, j) {
                    if f[i][j] == f[ni][nj] {
                        memo[i][j] = 0;
                        ok = true;
                        queue.push((0, i, j));
                        break;
                    }
                }
            }
        }
    }

    while let Some((priority, i, j)) = queue.pop() {
        for (ni, nj) in neigh.iter(i, j) {
            if memo[ni][nj] <= memo[i][j] + 1 {
                continue;
            }
            memo[ni][nj] = memo[i][j] + 1;
            queue.push((priority - 1, ni, nj));
        }
    }

    // trace!(ok);
    // for i in 0..h {
    //     trace!(i, &memo[i]);
    // }

    for _ in 0..t {
        let i: usize = sc.cin::<usize>() - 1;
        let j: usize = sc.cin::<usize>() - 1;
        let p: u64 = sc.cin();
        if !ok {
            put!(f[i][j]);
            continue;
        }
        if p < memo[i][j] {
            put!(f[i][j])
        } else {
            if (p - memo[i][j]) % 2 == 1 {
                put!(flip(f[i][j]));
            } else {
                put!(f[i][j]);
            }
        }
    }
}

fn flip(c: char) -> char {
    match c {
        '0' => '1',
        _ => '0',
    }
}

use std::collections::VecDeque;
use std::io::{self, Write};
use std::str::FromStr;

struct Scanner {
    stdin: io::Stdin,
    buffer: VecDeque<String>,
}
impl Scanner {
    fn new() -> Self {
        Scanner {
            stdin: io::stdin(),
            buffer: VecDeque::new(),
        }
    }
    fn cin<T: FromStr>(&mut self) -> T {
        while self.buffer.is_empty() {
            let mut line = String::new();
            let _ = self.stdin.read_line(&mut line);
            for w in line.split_whitespace() {
                self.buffer.push_back(String::from(w));
            }
        }
        self.buffer.pop_front().unwrap().parse::<T>().ok().unwrap()
    }
    fn chars(&mut self) -> Vec<char> {
        self.cin::<String>().chars().collect()
    }
    fn vec<T: FromStr>(&mut self, n: usize) -> Vec<T> {
        (0..n).map(|_| self.cin()).collect()
    }
}


#![allow(unused_imports, unused_macros, dead_code)]

macro_rules! min {
    (.. $x:expr) => {{
        let mut it = $x.iter();
        it.next().map(|z| it.fold(z, |x, y| min!(x, y)))
    }};
    ($x:expr) => ($x);
    ($x:expr, $($ys:expr),*) => {{
        let t = min!($($ys),*);
        if $x < t { $x } else { t }
    }}
}
macro_rules! max {
    (.. $x:expr) => {{
        let mut it = $x.iter();
        it.next().map(|z| it.fold(z, |x, y| max!(x, y)))
    }};
    ($x:expr) => ($x);
    ($x:expr, $($ys:expr),*) => {{
        let t = max!($($ys),*);
        if $x > t { $x } else { t }
    }}
}
macro_rules! ewriteln {
    ($($args:expr),*) => { let _ = writeln!(&mut std::io::stderr(), $($args),*); };
}
macro_rules! trace {
    ($x:expr) => { ewriteln!(">>> {} = {:?}", stringify!($x), $x) };
    ($($xs:expr),*) => { trace!(($($xs),*)) }
}
macro_rules! put {
    (.. $x:expr) => {{
        let mut it = $x.iter();
        if let Some(x) = it.next() { print!("{}", x); }
        for x in it { print!(" {}", x); }
        println!("");
    }};
    ($x:expr) => { println!("{}", $x) };
    ($x:expr, $($xs:expr),*) => { print!("{} ", $x); put!($($xs),*) }
}

const M: i64 = 1_000_000_007;

macro_rules! list {
    ($($t:tt)*) => {{ let mut r = vec![]; list_inner!(r, $($t)*); r }}
}
macro_rules! list_inner {
    ($r:expr) => {};
    ($r:expr, $e:expr) => { $r.push($e) };
    ($r:expr, $e:expr;) => { $r.push($e) };
    ($r:expr, $e:expr; for $k:ident in $range:expr) => { for $k in $range { list_inner!($r, $e) } };
    ($r:expr, $e:expr; if $cond:expr) => { if $cond { list_inner!($r, $e) } };
    ($r:expr, $e:expr; for $k:ident in $range:expr ; $($t:tt)*) => { for $k in $range { list_inner!($r, $e ; $($t)*); } };
    ($r:expr, $e:expr; if $cond:expr ; $($t:tt)*) => { if $cond { list_inner!($r, $e ; $($t)*); } };
}

mod neighbor {
    pub struct Grid4(pub usize, pub usize);
    impl Grid4 {
        pub fn iter(&self, i: usize, j: usize) -> NeighborIter<(usize, usize)> {
            NeighborIter::new(list! {
                (i + s - 1, j + t - 1);
                for s in 0..3;
                for t in 0..3;
                if (s + t) % 2 == 1;
                if (1..self.0 + 1).contains(&(i + s));
                if (1..self.1 + 1).contains(&(j + t));
            })
        }
    }
    pub struct Grid8(pub usize, pub usize);
    impl Grid8 {
        pub fn iter<'a>(&'a self, i: usize, j: usize) -> NeighborIter<(usize, usize)> {
            NeighborIter::new(list! {
                (i + s - 1, j + t - 1);
                for s in 0..3;
                for t in 0..3;
                if s * t != 1;
                if (1..self.0 + 1).contains(&(i + s));
                if (1..self.1 + 1).contains(&(j + t));
            })
        }
    }
    pub struct NeighborIter<T>(Vec<T>, usize);
    impl<T> NeighborIter<T> {
        fn new(data: Vec<T>) -> Self {
            NeighborIter(data, 0)
        }
    }
    impl<T: Copy> Iterator for NeighborIter<T> {
        type Item = T;
        fn next(&mut self) -> Option<Self::Item> {
            if self.0.len() > self.1 {
                self.1 += 1;
                Some(self.0[self.1 - 1])
            } else {
                None
            }
        }
    }
}

fn main() {
    let mut sc = Scanner::new();
    let h: usize = sc.cin();
    let w: usize = sc.cin();
    let t: usize = sc.cin();

    let f: Vec<Vec<char>> = (0..h).map(|_| sc.chars()).collect();
    let neigh = neighbor::Grid4(h, w);

    let mut memo: Vec<Vec<usize>> = vec![vec![h + w; w]; h];
    let mut queue = std::collections::BinaryHeap::new();
    let mut ok = false;
    {
        for i in 0..h {
            for j in 0..w {
                for (ni, nj) in neigh.iter(i, j) {
                    if f[i][j] == f[ni][nj] {
                        memo[i][j] = 0;
                        ok = true;
                        queue.push((0, i, j));
                        break;
                    }
                }
            }
        }
    }

    while let Some((priority, i, j)) = queue.pop() {
        for (ni, nj) in neigh.iter(i, j) {
            if memo[ni][nj] <= memo[i][j] + 1 {
                continue;
            }
            memo[ni][nj] = memo[i][j] + 1;
            queue.push((priority - 1, ni, nj));
        }
    }

    // trace!(ok);
    // for i in 0..h {
    //     trace!(i, &memo[i]);
    // }

    for _ in 0..t {
        let i: usize = sc.cin::<usize>() - 1;
        let j: usize = sc.cin::<usize>() - 1;
        let p: usize = sc.cin();
        if !ok {
            put!(f[i][j]);
            continue;
        }
        if p < memo[i][j] {
            put!(f[i][j])
        } else {
            if (p - memo[i][j]) % 2 == 1 {
                put!(flip(f[i][j]));
            } else {
                put!(f[i][j]);
            }
        }
    }
}

fn flip(c: char) -> char {
    match c {
        '0' => '1',
        _ => '0',
    }
}

use std::collections::VecDeque;
use std::io::{self, Write};
use std::str::FromStr;

struct Scanner {
    stdin: io::Stdin,
    buffer: VecDeque<String>,
}
impl Scanner {
    fn new() -> Self {
        Scanner {
            stdin: io::stdin(),
            buffer: VecDeque::new(),
        }
    }
    fn cin<T: FromStr>(&mut self) -> T {
        while self.buffer.is_empty() {
            let mut line = String::new();
            let _ = self.stdin.read_line(&mut line);
            for w in line.split_whitespace() {
                self.buffer.push_back(String::from(w));
            }
        }
        self.buffer.pop_front().unwrap().parse::<T>().ok().unwrap()
    }
    fn chars(&mut self) -> Vec<char> {
        self.cin::<String>().chars().collect()
    }
    fn vec<T: FromStr>(&mut self, n: usize) -> Vec<T> {
        (0..n).map(|_| self.cin()).collect()
    }
}


package main

import (
	"bufio"
	. "fmt"
	"io"
	"os"
)

// github.com/EndlessCheng/codeforces-go
func CF1350E(_r io.Reader, _w io.Writer) {
	in := bufio.NewReader(_r)
	out := bufio.NewWriter(_w)
	defer out.Flush()
	type pair struct{ x, y int }
	dir4 := [...]pair{{-1, 0}, {1, 0}, {0, -1}, {0, 1}}

	var n, m, t, x, y int
	var p int64
	Fscan(in, &n, &m, &t)
	g := make([][]byte, n)
	dep := make([][]int, n)
	for i := range g {
		Fscan(in, &g[i])
		dep[i] = make([]int, m)
	}
	q := []pair{}
	for i, row := range g {
		for j, b := range row {
			for _, d := range dir4 {
				if x, y := i+d.x, j+d.y; x >= 0 && x < n && y >= 0 && y < m && g[x][y] == b {
					dep[i][j] = 1
					q = append(q, pair{i, j})
					break
				}
			}
		}
	}
	for len(q) > 0 {
		p := q[0]
		q = q[1:]
		for _, d := range dir4 {
			if x, y := p.x+d.x, p.y+d.y; x >= 0 && x < n && y >= 0 && y < m && dep[x][y] == 0 {
				dep[x][y] = dep[p.x][p.y] + 1
				q = append(q, pair{x, y})
			}
		}
	}
	for ; t > 0; t-- {
		Fscan(in, &x, &y, &p)
		c := g[x-1][y-1] - '0'
		d := dep[x-1][y-1]
		if d == 0 {
			Fprintln(out, c)
			continue
		}
		p -= int64(d - 1)
		if p <= 0 {
			Fprintln(out, c)
		} else {
			Fprintln(out, byte(p&1)^c)
		}
	}
}

func main() { CF1350E(os.Stdin, os.Stdout) }


import sys
from collections import deque

readline = sys.stdin.readline
readlines = sys.stdin.readlines
ns = lambda: readline().rstrip()
ni = lambda: int(readline().rstrip())
nm = lambda: map(int, readline().split())
nl = lambda: list(map(int, readline().split()))
prn = lambda x: print(*x, sep='\n')

def solve():
    n, m, t = nm()
    g = [list(map(int, list(input()))) for _ in range(n)]
    b = [[10**18 + 5]*m for _ in range(n)]
    q = deque()
    for i in range(n):
        for j in range(m):
            if j < m-1 and g[i][j] == g[i][j+1]:
                b[i][j] = b[i][j+1] = 0
            if i < n-1 and g[i][j] == g[i+1][j]:
                b[i][j] = b[i+1][j] = 0
            if b[i][j] == 0:
                q.append(i*m + j)
    while q:
        v = q.popleft()
        y, x = divmod(v, m)
        for ny, nx in [(y+1, x), (y-1, x), (y, x+1), (y, x-1)]:
            if 0 <= ny < n and 0 <= nx < m and b[ny][nx] > b[y][x] + 1:
                b[ny][nx] = b[y][x] + 1
                q.append(ny*m + nx)
    for _ in range(t):
        y, x, p = nm()
        y -= 1; x -= 1
        if b[y][x] >= p:
            print(g[y][x])
        else:
            print(g[y][x] ^ (p - b[y][x]) & 1)
    return

solve()

# T = ni()
# for _ in range(T):
#     solve()


def main():
    import sys
    import collections
    input=lambda: sys.stdin.readline().rstrip()
    n,m,t=map(int,input().split())
    T=[input() for _ in range(n)]
    C=[0]*(n*m)
    d=((1,0),(0,1),(-1,0),(0,-1))
    Q=collections.deque()
    for ij in range(n*m):
      i,j=ij//m,ij%m
      for dx,dy in d:
        if 0<=i+dx<n and 0<=j+dy<m and T[i][j]==T[i+dx][j+dy]:
          C[ij]=1
          Q.append(ij)
          break
      else:
        continue
    while Q:
      q=Q.popleft()
      i,j=q//m,q%m
      for dx,dy in d:
        if 0<=i+dx<n and 0<=j+dy<m and C[(i+dx)*m+j+dy]==0:
          C[(i+dx)*m+j+dy]=C[q]+1
          Q.append((i+dx)*m+j+dy)
    for _ in range(t):
      i,j,p=map(int,input().split())
      i-=1
      j-=1
      if C[i*m+j]>0 and max(0,p+1-C[i*m+j])%2==1:
        if T[i][j]=="0":
          print(1)
        else:
          print(0)
      else:
        if T[i][j]=="0":
          print(0)
        else:
          print(1)
main()