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++: #include <iostream>
#include <vector>
#include <queue>

using namespace std;
typedef vector<int> vec;
typedef vector<vec> vvec;
typedef vector<vvec> vvvec;
typedef vector<vvvec> vvvvec;

struct state {
    int x, y;
    int front, right, down;
};

const int INF = 1145141919;
int h, w;

bool inRange(int x, int y) {
    return 0 <= x && x < h && 0 <= y && y < w;
}

int main() {
    cin >> h >> w;
    vector<string> ban(h);
    for (int i = 0; i < h; i++)cin >> ban[i];

    vvvvec dis(h, vvvec(w, vvec(7, vec(7, INF))));
    dis[0][0][2][3] = 0;
    queue<state> que;
    que.push({0, 0, 2, 3, 6});
    while (!que.empty()) {
        auto now = que.front();
        que.pop();
        int cost = dis[now.x][now.y][now.front][now.right] + 1;

        if (inRange(now.x - 1, now.y)) {
            state after = {now.x - 1, now.y, now.down, now.right, 7 - now.front};
            if (ban[after.x][after.y] - '0' == after.down && dis[after.x][after.y][after.front][after.right] > cost) {
                dis[after.x][after.y][after.front][after.right] = cost;
                que.push(after);
            }
        }
        if (inRange(now.x + 1, now.y)) {
            state after = {now.x + 1, now.y, 7 - now.down, now.right, now.front};
            if (ban[after.x][after.y] - '0' == after.down && dis[after.x][after.y][after.front][after.right] > cost) {
                dis[after.x][after.y][after.front][after.right] = cost;
                que.push(after);
            }
        }
        if (inRange(now.x, now.y - 1)) {
            state after = {now.x, now.y - 1, now.front, now.down, 7 - now.right};
            if (ban[after.x][after.y] - '0' == after.down && dis[after.x][after.y][after.front][after.right] > cost) {
                dis[after.x][after.y][after.front][after.right] = cost;
                que.push(after);
            }
        }
        if (inRange(now.x, now.y + 1)) {
            state after = {now.x, now.y + 1, now.front, 7 - now.down, now.right};
            if (ban[after.x][after.y] - '0' == after.down && dis[after.x][after.y][after.front][after.right] > cost) {
                dis[after.x][after.y][after.front][after.right] = cost;
                que.push(after);
            }
        }
    }

    bool ret = false;
    for (int i = 0; i <= 6; i++) {
        for (int j = 0; j <= 6; j++) {
            if (dis[h - 1][w - 1][i][j] < INF)ret = true;
        }
    }

    cout << (ret ? "YES" : "NO") << endl;
    return 0;
}

C++: #include <bits/stdc++.h>
using namespace std;

int main(){
    int H, W;
    cin >> H >> W;
    int S[100][100];
    for(int i=0; i<H; i++){
        string s;
        cin >> s;
        for(int j=0; j<W; j++) S[i][j] = (s[j] == '#' ? -1 : s[j]-'0');
    }

    auto inside = [&](int i, int j){ return i>=0 && i<H && j>=0 && j<W && S[i][j] != -1; };
    int dx[] = {-1, 1, 0, 0};
    int dy[] = {0, 0, -1, 1};
    auto bottom = [](int i, int j){
        if(i%4 == 0){
            vector<int> v = {6, 3, 1, 4};
            return v[j%4];
        }
        if(i%4 == 2){
            vector<int> v = {1, 3, 6, 4};
            return v[j%4];
        }
        if(j%4 == 0){
            vector<int> v = {6, 2, 1, 5};
            return v[i%4];
        }
        if(j%4 == 2){
            vector<int> v = {1, 2, 6, 5};
            return v[i%4];
        }
        exit(-1);
    };

    bool exist[100][100] = {0};
    exist[0][0] = 1;
    queue<vector<int>> que;
    que.push({0, 0});
    while(que.size()){
        auto v = que.front(); que.pop();
        int i = v[0], j = v[1];
        for(int k=0; k<4; k++){
            int x = i+dx[k], y = j+dy[k];
            if(!inside(x, y)) continue;
            if(exist[x][y]) continue;
            if(S[x][y] == bottom(x, y)){
                exist[x][y] = 1;
                que.push({x, y});
            }
        }
    }
    cout << (exist[H-1][W-1] ? "YES" : "NO") << endl;
    return 0;
}

C++: // g++ -std=c++11 a.cpp
#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
#include<map>
#include<set>
#include<unordered_map>
#include<utility>
#include<cmath>
#include<random>
#include<cstring>
#include<queue>
#include<stack>
#include<bitset>
#include<cstdio>
#include<sstream>
#include<iomanip>
#include<assert.h>
#include<typeinfo>
#define loop(i,a,b) for(long long i=a;i<b;i++)
#define rep(i,a) loop(i,0,a)
#define FOR(i,a) for(auto i:a)
#define pb push_back
#define all(in) in.begin(),in.end()
#define shosu(x) fixed<<setprecision(x)
#define show1d(v) {rep(_,v.size())cout<<" "<<v[_];cout<<endl;}
#define show2d(v) {rep(__,v.size())show1d(v[__]);}
using namespace std;
//kaewasuretyuui
typedef long long ll;
#define int ll
typedef int Def;
typedef pair<Def,Def> pii;
typedef vector<Def> vi;
typedef vector<vi> vvi;
typedef vector<pii> vp;
typedef vector<vp> vvp;
typedef vector<string> vs;
typedef vector<double> vd;
typedef vector<vd> vvd;
typedef pair<Def,pii> pip;
typedef vector<pip>vip;
#define mt make_tuple
typedef tuple<int,int,int,int> tp;
typedef vector<tp> vt;
template<typename A,typename B>bool cmin(A &a,const B &b){return a>b?(a=b,true):false;}
template<typename A,typename B>bool cmax(A &a,const B &b){return a<b?(a=b,true):false;}
const double PI=acos(-1);
const double EPS=1e-9;
Def inf = sizeof(Def) == sizeof(long long) ? 2e18 : 1e9+10;
int dx[]={-1,0,1,0};
int dy[]={0,1,0,-1};
#define yes cout<<"YES\n"
#define no cout<<"NO\n"

int n,m;
vs in;
void dfs(int x,int y){
	if(in[x][y]=='!'||in[x][y]=='#')return;
	in[x][y]='!';
	rep(i,4){
		int nx=x+dx[i],ny=y+dy[i];
		if(nx<0||nx>=n||ny<0||ny>=m)continue;
		dfs(nx,ny);
	}
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	
	cin>>n>>m;
	in=vs(n);
	rep(i,n)cin>>in[i];
	string t[4]={"6314","2#2#","1364","5#5#"};
	rep(i,n)rep(j,m)if(in[i][j]-t[i%4][j%4])in[i][j]='#';
	
	dfs(0,0);
	if(in[n-1][m-1]=='!')yes;
	else no;
}