Go: package main

import "fmt"

var h, w int
var maze [][]byte

var visited [][]bool

type dice struct {
	top, bottom, right, left, up, down int
}

func move(d *dice, dir byte) {
	now := d.top
	switch dir {
	case 'N':
		d.top = d.down
		d.down = d.bottom
		d.bottom = d.up
		d.up = now
	case 'S':
		d.top = d.up
		d.up = d.bottom
		d.bottom = d.down
		d.down = now
	case 'W':
		d.top = d.right
		d.right = d.bottom
		d.bottom = d.left
		d.left = now
	case 'E':
		d.top = d.left
		d.left = d.bottom
		d.bottom = d.right
		d.right = now
	}
}

var dx = [4]int{1, -1, 0, 0}
var dy = [4]int{0, 0, 1, -1}

func dfs(x, y int, d *dice) bool {
	// fmt.Printf("dfs(%d,%d) en: dice.bottom=%d\n", x, y, d.bottom)
	visited[y][x] = true // (x,y)に到達した
	if (y == h-1) && (x == w-1) {
		return true
	}
	// 4方のマス目に進めるかどうかチェック
	for i := 0; i < 4; i++ {
		nx := x + dx[i]
		ny := y + dy[i]
		dir := []byte{'E', 'W', 'S', 'N'}
		dc := *d
		move(&dc, dir[i]) // 動かしてみる
		if 0 <= nx && nx < w && 0 <= ny && ny < h && maze[ny][nx] != '#' && !visited[ny][nx] && dc.bottom == int(maze[ny][nx]-'0') {
			// fmt.Printf("move dir %c, new bottom=%d, move to (nx, ny)=(%d,%d)\n", dir[i], dc.bottom, nx, ny)
			if dfs(nx, ny, &dc) {
				return true
			}
		} else {
			continue
		}
	}
	return false
}

func main() {
	fmt.Scan(&h, &w)
	maze = make([][]byte, h)
	visited = make([][]bool, h)
	for i := 0; i < h; i++ {
		visited[i] = make([]bool, w)
		maze[i] = make([]byte, w)
		fmt.Scan(&maze[i])
	}
	// fmt.Println("h", h, "w", w, "maze", maze)
	// visited[0][0] = true
	var d dice
	d.bottom = 6
	d.top = 1
	d.right = 3
	d.left = 4
	d.down = 2
	d.up = 5
	if dfs(0, 0, &d) {
		fmt.Println("YES")
	} else {
		fmt.Println("NO")
	}
}

C++: #pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#pragma GCC optimize("unroll-loops")
#pragma warning(disable : 4996)
#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<math.h>
#include<iomanip>
#include<set>
#include<numeric>
#include<cstring>
#include<cstdio>
#include<functional>
#include<bitset>
#include<limits.h>
#include<cassert>
#include<iterator>
#include<complex>
#include<stack>
#include<unordered_map>
#include<unordered_set>
#include<time.h>
#include<random>
#include<array>


using namespace std;

#define REP(i, n) for(int i = 0;i < n;++i)
#define REPR(i, n) for(int i = n-1;i >= 0;--i)
#define FOR(i, m, n) for(int i = m;i < n;++i)
#define FORR(i, m, n) for(int i = m-1;i >= n;--i)
#define SORT(v, n) sort(v, v+n);
#define VSORT(v) sort(v.begin(), v.end());
#define REVERSE(v,n) reverse(v,v+n);
#define VREVERSE(v) reverse(v.begin(), v.end())
#define ll long long
#define print(x) cout<<(x)<<'\n'
#define pe(x) cout<<(x)<<" "
#define DEBUG(x) cout<<#x<<": "<<x<<endl
#define lb(v,n) lower_bound(v.begin(), v.end(), (n))
#define ub(v,n) upper_bound(v.begin(), v.end(), (n))
#define int long long
//#define double long double
#define all(x) (x).begin(), (x).end()
#define print_space(v) REP(i,v.size())cout << v[i] << ((i == v.size() - 1) ? "\n" : " ")
template<typename T1, typename T2> inline void chmin(T1 & a, T2 b) { if (a > b) a = b; }
template<typename T1, typename T2> inline void chmax(T1& a, T2 b) { if (a < b) a = b; }
typedef pair<int, int>P;
typedef array<int, 3> arr3;
std::random_device rd;
std::mt19937 mt(rd());
constexpr int MOD = 1e9 + 7; constexpr int MAX = 200020;
const double pi = acos(-1); constexpr double EPS = 1e-8;
constexpr ll INF = 1e18;
bool can[101][101][7][7][7];

char A[101][101];
int H, W;

bool vis[101][101][7][7][7];
void solve() {
	cin >> H >> W;
	REP(i, H) {
		REP(j, W) {
			cin >> A[i][j];
		}
	}
	queue<array<int,5>>que;
	que.push({ 0,0,6,2,3 });
	vis[0][0][6][2][3] = true;
	while (!que.empty()) {
		array<int, 5>a = que.front();
		que.pop();
		int x = a[0];
		int y = a[1];
		int B = a[2];
		int D = a[3];
		int R = a[4];
		int T = 7 - B;
		int U = 7 - D;
		int L = 7 - R;
		vis[x][y][B][D][R] = true;
		//D
		if (x == H - 1 && y == W - 1) {
			print("YES"); exit(0);
		}
		if (x + 1 < H) {
			if (D == A[x + 1][y] - '0' && !vis[x + 1][y][D][T][R]) {
				vis[x + 1][y][D][T][R] = true;
				que.push({ x + 1,y,D,T,R });
			}
		}
		if (x - 1 >= 0) {
			if (U == A[x - 1][y] - '0' && !vis[x - 1][y][U][B][R]) {
				vis[x - 1][y][U][B][R] = true;
				que.push({ x - 1,y,U,B,R });
			}
		}
		if (y + 1 < W) {
			if (R == A[x][y + 1] - '0' && !vis[x][y + 1][R][D][T]) {
				vis[x][y + 1][R][D][T] = true;
				que.push({ x,y + 1,R,D,T });
			}
		}
		if (y - 1 >= 0) {
			if (L == A[x][y - 1] - '0' && !vis[x][y - 1][L][D][B]) {
				vis[x][y - 1][L][D][B] = true;
				que.push({ x,y - 1,L,D,B });
			}
		}
	}
	print("NO");
}

signed main() {
	cin.tie(0);
	ios::sync_with_stdio(false);
	//int q; cin >> q;
	//while (q--)
	solve();
}

C++: #include <iostream>
#include <vector>
#include <queue>
using namespace std;
#define rep(i, n) for(int i=0;i<n;i++)
using P = pair<int, int>;
int H, W;
vector<vector<int>> G;
vector<vector<int>> used;
void dfs(P v) {
  used[v.first][v.second] = true;
  if(v.first == H && v.second == W) return;

  if(G[v.first+1][v.second] && !used[v.first+1][v.second]) dfs(make_pair(v.first+1, v.second));
  if(G[v.first-1][v.second] && !used[v.first-1][v.second]) dfs(make_pair(v.first-1, v.second));
  if(G[v.first][v.second-1] && !used[v.first][v.second-1]) dfs(make_pair(v.first, v.second-1));
  if(G[v.first][v.second+1] && !used[v.first][v.second+1]) dfs(make_pair(v.first, v.second+1));
}
int main() {
  int h, w;
  cin >> h >> w;
  H = h; W = w;
  G.resize(h+2);
  rep(i, h+2) G[i].resize(w+2);
  used = G;
  rep(i, h) rep(j, w) {
    if((i+1) % 2 == 0 && (j+1) % 2 == 0) {
      char c;
      cin >> c;
    }
    else {
      char c;
      cin >> c;
      if(c == '#') G[i+1][j+1] = 0;
      else G[i+1][j+1] = c - '0';
    }
  }
  if(G[h][w] == 0) {
    cout << "NO" << endl;
    return 0;
  }
  rep(i, h) rep(j, w) {
    if((i+1) % 2 == 0 && (j+1) % 2 == 0) continue;
    int x = (j+1) % 4;
    int y = (i+1) % 4;
    if(y == 1) {
      if(x == 1) {
        if(G[i+1][j+1] != 6) G[i+1][j+1] = 0;
      }
      else if(x == 2) {
        if(G[i+1][j+1] != 3) G[i+1][j+1] = 0;
      }
      else if(x == 3) {
        if(G[i+1][j+1] != 1) G[i+1][j+1] = 0;
      }
      else if(x == 0) {
        if(G[i+1][j+1] != 4) G[i+1][j+1] = 0;
      }
    }
    else if(y == 2) {
      if(G[i+1][j+1] != 2) G[i+1][j+1] = 0;
    }
    else if(y == 3) {
      if(x == 1) {
        if(G[i+1][j+1] != 1) G[i+1][j+1] = 0;
      }
      else if(x == 2) {
        if(G[i+1][j+1] != 3) G[i+1][j+1] = 0;
      }
      else if(x == 3) {
        if(G[i+1][j+1] != 6) G[i+1][j+1] = 0;
      }
      else if(x == 0) {
        if(G[i+1][j+1] != 4) G[i+1][j+1] = 0;
      }
    }
    else if( y == 0) {
      if(G[i+1][j+1] != 5) G[i+1][j+1] = 0;
    }
  }
  if(G[h][w] == 0) {
    cout << "NO" << endl;
    return 0;
  }
  P init = make_pair(1, 1);
  dfs(init);
  if(used[h][w]) cout << "YES" << endl;
  else cout << "NO" << endl;
}