#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define int long long
const int N = 35;
const int LARGE = 1000005;
const int INF = 1e9+5;
int n, m, sx, sy, ex, ey, tot = 1;
int map[N][N], point[N][N], d[LARGE], head[LARGE], to[LARGE];
bool vis[N][N], inq[LARGE];
int dx[9] = {0, 1, 1, 2, 2, -1, -1, -2, -2};
int dy[9] = {0, 2, -2, 1, -1, 2, -2, 1, -1};
queue<int> q;
struct node{
int u;
int v;
}edge[100005];
inline void add(int x, int y)
{
edge[++tot].u = head[x];
edge[tot].v = y;
head[x] = tot;
}
inline int read(){
char ch = getchar();
int x = 0;
while('0' <= ch && ch <= '9'){
x = x*10+ch-'0';
ch = getchar();
}
return x;
}
inline bool check(int x, int y)
{
if(x >= 1 && x <= n && y >= 1 && y <= n) return true;
return false;
}
inline void dfs(int step, int x, int y)
{
if(vis[x][y]) return;
vis[x][y] = true;
for(int i = 1;i <= 8;i++){
int nowx = x+dx[i], nowy = y+dy[i];
if(!check(nowx, nowy) || vis[nowx][nowy]) continue;
if(map[nowx][nowy] == 1) dfs(step, nowx, nowy);
else if(map[nowx][nowy] != 2){
vis[nowx][nowy] = true;
add(step, point[nowx][nowy]);
}
}
}
signed main()
{
n = read();m = read();
for(int i = 1;i <= n;i++){
for(int j = 1;j <= m;j++){
map[i][j] = read();
point[i][j] = (i-1)*m+j;
if(map[i][j] == 3) sx = i, sy = j;
if(map[i][j] == 4) ex = i, ey = j;
}
}
for(int i = 1;i <= n;i++){
for(int j = 1;j <= m;j++){
if(!map[i][j] || map[i][j] == 3){
memset(vis, 0, sizeof(vis));
dfs(point[i][j], i, j);
}
}
}
int s = point[sx][sy], t = point[ex][ey];
memset(d, INF, sizeof(d));
d[s] = 0;to[s] = 1;
inq[s] = true;q.push(s);
while(!q.empty()){
int u = q.front();q.pop();
inq[u] = false;
for(int i = head[u];i;i = edge[i].u){
if(d[edge[i].v] > d[u]+1){
d[edge[i].v] = d[u]+1;
to[edge[i].v] = to[u];
if(!inq[edge[i].v]){
q.push(edge[i].v);
inq[edge[i].v] = true;
}
}else if(d[edge[i].v] == d[u]+1) to[edge[i].v] += to[u];
}
}
if(d[t] < INF) printf("%d\n%d",d[t]-1, to[t]);
else printf("-1");
return 0;
}