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++: /*
さいころ

mapを使っているところは普通のサイコロとかなら配列で大丈夫
まぁ、せいぜいO(log24)なのでOKか

参考:
http://www.prefield.com/algorithm/misc/dice.html
参考:
https://onlinejudge.u-aizu.ac.jp/beta/review.html#KUPC2020Spring/4276858
verify:
https://onlinejudge.u-aizu.ac.jp/beta/room.html#KUPC2020Spring/workspace
*/
#include <bits/stdc++.h>
using namespace std;

//up(上),down(下),front(前),back(後ろ),right(右),left(左)
enum FACE{UP,DOWN,FRONT,BACK,RIGHT,LEFT};
template<typename T>
struct Dice{
    T var[6];
    T& operator[](FACE f){return var[f];}

    void rollR(){roll(UP,LEFT,DOWN,RIGHT);}
    void rollL(){roll(UP,RIGHT,DOWN,LEFT);}
    void rollU(){roll(UP,FRONT,DOWN,BACK);}
    void rollD(){roll(UP,BACK,DOWN,FRONT);}
    void rollT(){roll(FRONT,RIGHT,BACK,LEFT);}
    void rollH(){roll(FRONT,LEFT,BACK,RIGHT);}
    void roll(FACE a,FACE b,FACE c,FACE d){
        int tmp=var[a];
        var[a]=var[b];
        var[b]=var[c];
        var[c]=var[d];
        var[d]=tmp;
    }
    bool operator==(const Dice &d)const noexcept{
        for(int i=0;i<6;i++){
            if(var[i]!=d.var[i]) return false;
        }
        return true;
    }

};

template<typename T>
struct allDice{
    using ptt=pair<T,T>;
    map<ptt,int> M;
    vector<Dice<T>> V;

    allDice(Dice<T> d){
        int cnt=0;
        V.resize(24);
        for(int k=0;k<6;(k&1?d.rollR():d.rollD()),k++){
            for(int i=0;i<4;d.rollT(),i++,cnt++){
                V[cnt]=d;
                M[ptt(d[UP],d[FRONT])]=cnt;
            }
        }
    }
    Dice<T> operator[](int idx){return V[idx];};

    Dice<T> find(T up,T front){return V[ M[ptt(up,front)] ];}

    Dice<T> find(FACE f,T a,FACE g,T b){
        for(int i=0;i<24;i++){
            if(V[i][f]==a && V[i][g]==b) return V[i];
        }
    }

    int id(Dice<T> &d){return M[ptt(d[UP],d[FRONT])];}

};

signed main(){
    int H,W;
    cin>>H>>W;
    Dice<int> d;
    d[UP]=1; d[DOWN]=6; d[RIGHT]=3; d[LEFT]=4; 
    d[FRONT]=2; d[BACK]=5;
    allDice<int> D(d);
    queue<tuple<int,int,int>> que;
    char S[110][110];
    bool flag[110][110][24];
    for(int i=0;i<110;i++){
        for(int j=0;j<110;j++){
            for(int k=0;k<24;k++){
                flag[i][j][k]=false;
            }
        }
    }
    for(int i=1;i<=H;i++){
        for(int j=1;j<=W;j++) cin>>S[i][j];
    }
    que.emplace(1,1,D.id(d));
    flag[1][1][D.id(d)]=true;
    while(!que.empty()){
        int h,w,id;
        tie(h,w,id)=que.front(); que.pop();
        auto d=D[id];
        auto r=d; r.rollR();
        auto l=d; l.rollL();
        auto dow=d; dow.rollD();
        auto u=d; u.rollU();
        if(r[DOWN]==(int)(S[h][w+1]-'0')){
            if(!flag[h][w+1][D.id(r)]) que.emplace(h,w+1,D.id(r)),flag[h][w+1][D.id(r)]=true;
        }
        if(l[DOWN]==(int)(S[h][w-1]-'0')){
            if(!flag[h][w-1][D.id(l)]) que.emplace(h,w-1,D.id(l)),flag[h][w-1][D.id(l)]=true;
        }
        if(dow[DOWN]==(int)(S[h+1][w]-'0')){
            if(!flag[h+1][w][D.id(dow)]) que.emplace(h+1,w,D.id(dow)),flag[h+1][w][D.id(dow)]=true;
        }
        if(u[DOWN]==(int)(S[h-1][w]-'0')){
            if(!flag[h-1][w][D.id(u)]) que.emplace(h-1,w,D.id(u)),flag[h-1][w][D.id(u)]=true;
        }
        
    }
    for(int i=0;i<24;i++){
        if(flag[H][W][i]){
            cout<<"YES"<<endl;
            return 0;
        }
    }
    cout<<"NO"<<endl;
}

C++: #include <bits/stdc++.h>
using namespace std;
const int di[] = {+1,-1, 0, 0};
const int dj[] = { 0, 0,+1,-1};
int main() {
	int H, W;
	cin >> H >> W;
	vector<string> S(H);
	for (auto& x : S) cin >> x;

	vector<string> ptn = {
		"6314",
		"2 2 ",
		"1364",
		"5 5 ",
	};

	vector<vector<bool>> a(H, vector<bool>(W));
	for (int i = 0; i < H; ++ i) for (int j = 0; j < W; ++ j) a[i][j] = S[i][j] == ptn[i%4][j%4];

	queue<pair<int,int>> q;
	q.push({0,0});
	while (!q.empty()) {
		int i = q.front().first;
		int j = q.front().second;
		q.pop();
		if (i == H-1 && j == W-1) {
			cout << "YES" << endl;
			return 0;
		}
		for (int k = 0; k < 4; ++ k) {
			int ii = i + di[k];
			int jj = j + dj[k];
			if (0 <= ii && ii < H && 0 <= jj && jj < W && a[ii][jj]) {
				a[ii][jj] = false;
				q.push({ii,jj});
			}
		}
	}
	cout << "NO" << endl;
}