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 <bits/stdc++.h>
using namespace std;
using lint     = long long;
const lint inf = 1LL << 60;
const lint mod = 1000000007;

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int h, w;
    cin >> h >> w;
    vector<string> s(h);
    for (int i = 0; i < h; ++i) {
        cin >> s[i];
    }
    vector<vector<vector<vector<vector<int>>>>> visited(
        h, vector<vector<vector<vector<int>>>>(
               w, vector<vector<vector<int>>>(6, vector<vector<int>>(6, vector<int>(6, 0))))); // bottom, right,
    struct state {
        int i, j, k, l, m;
    };
    queue<state> q;
    q.push({0, 0, 5, 2, 1});
    visited[0][0][5][2][1] = 1;
    while (!q.empty()) {
        auto c = q.front();
        q.pop();
        if (c.i == h - 1 && c.j == w - 1) {
            cout << "YES"
                 << "\n";
            return 0;
        }
        // up
        if (c.i != 0) {
            int nk    = 5 - c.m;
            int nl    = c.l;
            int nm    = c.k;
            state nxt = {c.i - 1, c.j, nk, nl, nm};
            if (s[c.i - 1][c.j] - '1' == nk)
                if (visited[nxt.i][nxt.j][nxt.k][nxt.l][nxt.m] == 0) {
                    visited[nxt.i][nxt.j][nxt.k][nxt.l][nxt.m] = 1;
                    q.push(nxt);
                }
        }
        // right
        if (c.j != w - 1) {
            int nk    = c.l;
            int nl    = 5 - c.k;
            int nm    = c.m;
            state nxt = {c.i, c.j + 1, nk, nl, nm};
            if (s[c.i][c.j + 1] - '1' == nk)
                if (visited[nxt.i][nxt.j][nxt.k][nxt.l][nxt.m] == 0) {
                    visited[nxt.i][nxt.j][nxt.k][nxt.l][nxt.m] = 1;
                    q.push(nxt);
                }
        }
        // left
        if (c.j != 0) {
            int nk    = 5 - c.l;
            int nl    = c.k;
            int nm    = c.m;
            state nxt = {c.i, c.j - 1, nk, nl, nm};
            if (s[c.i][c.j - 1] - '1' == nk)
                if (visited[nxt.i][nxt.j][nxt.k][nxt.l][nxt.m] == 0) {
                    visited[nxt.i][nxt.j][nxt.k][nxt.l][nxt.m] = 1;
                    q.push(nxt);
                }
        }
        // down
        if (c.i != h - 1) {
            int nk    = c.m;
            int nl    = c.l;
            int nm    = 5 - c.k;
            state nxt = {c.i + 1, c.j, nk, nl, nm};
            if (s[c.i + 1][c.j] - '1' == nk)
                if (visited[nxt.i][nxt.j][nxt.k][nxt.l][nxt.m] == 0) {
                    visited[nxt.i][nxt.j][nxt.k][nxt.l][nxt.m] = 1;
                    q.push(nxt);
                }
        }
    }
    cout << "NO"
         << "\n";
    return 0;
}

C++: #include<iostream>
#include<tuple>
#include<vector>
#include<queue>
#include<algorithm>

using namespace std;

typedef tuple<int, int, vector<int>> T3;//座標、

int H, W;
char field[100 + 10][100 + 10];
bool visited[100 + 10][100 + 10];

int main() {
	cin >> H >> W;
	for (int i = 0; i < H; i++) {
		for (int j = 0; j < W; j++)cin >> field[i][j];
	}
	
	queue<T3> Q;
	vector<int> state = {1, 2, 3, 5, 4, 6};
	Q.push(make_tuple(0, 0, state));
	while (Q.size()) {
		auto now = Q.front();
		int x = get<0>(now), y = get<1>(now);
		auto ns = get<2>(now);
		Q.pop();
		if (x == H - 1 && y == W - 1) {
			cout << "YES" << endl;
			return 0;
		}

		//上向き
		if (x > 0 && field[x - 1][y] != '#' && !visited[x - 1][y]) {
			vector<int> newstate(6);
			newstate[0] = ns[1], newstate[1] = ns[5], newstate[2] = ns[2];
			newstate[3] = ns[0], newstate[4] = ns[4], newstate[5] = ns[3];
			if (newstate[5] == field[x - 1][y] - '0') {
				visited[x - 1][y] = true;
				Q.push(make_tuple(x - 1, y, newstate));
			}
		}
		
		//下向き
		if (x < H - 1 && field[x + 1][y] != '#' && !visited[x + 1][y]) {
			vector<int> newstate(6);
			newstate[0] = ns[3], newstate[1] = ns[0], newstate[2] = ns[2];
			newstate[3] = ns[5], newstate[4] = ns[4], newstate[5] = ns[1];
			if (newstate[5] == field[x + 1][y] - '0') {
				visited[x + 1][y] = true;
				Q.push(make_tuple(x + 1, y, newstate));
			}
		}
		
		//左向き
		if (y > 0 && field[x][y - 1] != '#' && !visited[x][y - 1]) {
			vector<int> newstate(6);
			newstate[0] = ns[2], newstate[1] = ns[1], newstate[2] = ns[5];
			newstate[3] = ns[3], newstate[4] = ns[0], newstate[5] = ns[4];
			if (newstate[5] == field[x][y - 1] - '0') {
				visited[x][y - 1] = true;
				Q.push(make_tuple(x, y - 1, newstate));
			}
		}
		
		//右向き
		if (y < W - 1 && field[x][y + 1] != '#' && !visited[x][y + 1]) {
			vector<int> newstate(6);
			newstate[0] = ns[4], newstate[1] = ns[1], newstate[2] = ns[0];
			newstate[3] = ns[3], newstate[4] = ns[5], newstate[5] = ns[2];
			if (newstate[5] == field[x][y + 1] - '0') {
				visited[x][y + 1] = true;
				Q.push(make_tuple(x, y + 1, newstate));
			}
		}
	}
	cout << "NO" << endl;
	return 0;
}