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++: // https://onlinejudge.u-aizu.ac.jp/beta/room.html#KUPC2020Spring/problems/B
#include <bits/stdc++.h>
using namespace std;
// #define int long long
#define REP(i, n) FOR(i, 0, n)
#define REPR(i, n) for (int i = n - 1; i >= 0; i--)
#define FOR(i, s, n) for (int i = (s), i##_len = (n); i < i##_len; ++i)
#define ALL(obj) (obj).begin(), (obj).end()
#define ALLR(obj) (obj).rbegin(), (obj).rend()
#define DIV(a, b) ((a - 1) / b + 1)

struct Dice {
    // Left, Right, Front, Back, Down, Up
    int l, r, f, b, d, u;
    bool operator<(const Dice &rhs) const {
        return l * 10 + r > rhs.l * 10 + rhs.r;
    }

    // y軸方向にプラス
    void RollN() {
        // ++y;
        int buff = d;
        d = b;
        b = u;
        u = f;
        f = buff;
    }

    // y軸方向にマイナス
    void RollS() {
        //  --y;
        int buff = d;
        d = f;
        f = u;
        u = b;
        b = buff;
    }

    // x軸方向にプラス
    void RollE() {
        // ++x;
        int buff = d;
        d = r;
        r = u;
        u = l;
        l = buff;
    }

    // x軸方向にマイナス
    void RollW() {
        // --x;
        int buff = d;
        d = l;
        l = u;
        u = r;
        r = buff;
    }

    // 90度→方向に回転
    void RollL() {
        // ----->
        int buff = f;
        f = l;
        l = b;
        b = r;
        r = buff;
    }

    // 90度←方向に回転
    void RollR() {
        // <------
        int buff = f;
        f = r;
        r = b;
        b = l;
        l = buff;
    }
};

struct dir {
    int y, x;
    Dice dice;
};

int H, W;
queue<dir> q;
vector<set<Dice>> st;
void qin(int y, int x, Dice d) {
    if (st[y * W + x].count(d) == 0) {
        q.push({y, x, d});
        st[y * W + x].insert(d);
    }
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin >> H >> W;
    vector<string> v(H);
    for (auto &x : v) {
        cin >> x;
    }
    auto dice = Dice();
    dice.u = 1;
    dice.f = 2;
    dice.r = 3;
    dice.l = 4;
    dice.b = 5;
    dice.d = 6;

    st.resize(H * W);
    // Y座標、X座標
    q.push({0, 0, dice});
    while (!q.empty()) {
        auto t = q.front();
        q.pop();
        if (t.y == H - 1 && t.x == W - 1) {
            cout << "YES\n";
            return 0;
        }
        if (t.y < H - 1) {
            auto u = t.dice;
            u.RollS();
            if (u.d == v[t.y + 1][t.x] - '0') {
                qin(t.y + 1, t.x, u);
            }
        }
        if (t.y > 0) {
            auto u = t.dice;
            u.RollN();
            if (u.d == v[t.y - 1][t.x] - '0') {
                qin(t.y - 1, t.x, u);
            }
        }
        if (t.x < W - 1) {
            auto u = t.dice;
            u.RollE();
            if (u.d == v[t.y][t.x + 1] - '0') {
                qin(t.y, t.x + 1, u);
            }
        }
        if (t.x > 0) {
            auto u = t.dice;
            u.RollW();
            if (u.d == v[t.y][t.x - 1] - '0') {
                qin(t.y, t.x - 1, u);
            }
        }
    }
    cout << "NO\n";

    return 0;
}

C++: #include <bits/stdc++.h>
using namespace std;
#define MOD 1000000007
//#define MOD 998244353
#define INF 1145141919810893364
//#define INF 810114514
//#define PI 3.141592653589
typedef pair<int,int> PP;
typedef long long ll;
#define int ll
#define setdouble setprecision
#define REP(i,n) for(int i=0;i<(n);++i)
#define OREP(i,n) for(int i=1;i<=(n);++i)
#define RREP(i,n) for(int i=(n)-1;i>=0;--i)
#define GOODBYE do { cout << "0" << endl; return 0; } while (false)
#define MM <<" "<<
#define Endl endl

signed main(void){
    int H,W;
    string S[120];
    cin >> H >> W;
    REP(i,H){
        cin >> S[i];
    }
    string T[4];
    T[0]="6314";
    T[1]="2-2-";
    T[2]="1364";
    T[3]="5-5-";
    
    int D[120][120]={};
    REP(i,H){
        REP(j,W){
            D[i][j]=0;
        }
    }
    REP(i,H){
        REP(j,W){
            if(S[i][j]==T[i%4][j%4]){
                D[i][j]=1;
            }
        }
    }
    
    /*REP(i,H){
        REP(j,W){
            cout << D[i][j] ;
        }cout << endl;
    }*/
    
    int visited[120][120]={};
    int dx[4]={1,0,-1,0};
    int dy[4]={0,1,0,-1};
    queue<pair<int,int>> Q;
    Q.push({0,0});
    while(!Q.empty()){
        pair<int,int> q;
        q=Q.front();
        Q.pop();
        visited[q.first][q.second]=1;
        if(q.first==W-1 && q.second==H-1){
            cout << "YES" << endl;
            return 0;
        }
        REP(k,4){
            int x=q.first+dx[k];
            int y=q.second+dy[k];
            if(0<=x && x<W && 0<=y && y<H){
                if(D[y][x]==1 && visited[x][y]==0){
                    Q.push({x,y});
                    visited[x][y]=1;
                }
            }
        }
        
    }
    cout << "NO" << endl;
    return 0;
}