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>
#include <array>
using namespace std;
using ULL = unsigned long long;
using UL = unsigned;
using LL = long long;
#define rep(i, n) for(UL i = 0; i < (n); i++)

template<class Ty>
using passive_queue = priority_queue<Ty, vector<Ty>, greater<Ty>>;

struct Problem {

	bool dp[102][102][4] = {};
	UL G[102][102];

	void Solve() {
		const UL nx[6][4][2] = {
			{{4,0}, {3,1}, {1,2}, {2,3}},
			{{0,0}, {3,0}, {5,2}, {2,0}},
			{{4,1}, {0,1}, {1,1}, {5,1}},
			{{4,3}, {5,3}, {1,3}, {0,3}},
			{{5,0}, {3,2}, {0,2}, {2,2}},
			{{1,0}, {3,3}, {4,2}, {2,1}}
		};
		UL H, W; cin >> H >> W;
		rep(y, H + 2) rep(x, W + 2) G[x][y] = -1;
		rep(y, H) rep(x, W) {
			char c; cin >> c;
			if (c == '#') G[x + 1][y + 1] = -1;
			else G[x + 1][y + 1] = 6 - (c - '0');
		}
		queue<pair<pair<UL, UL>, UL>> Q;
		Q.push({ { 1, 1 }, 0 });
		while (Q.size()) {
			UL x = Q.front().first.first;
			UL y = Q.front().first.second;
			UL i = Q.front().second;
			Q.pop();
			if (dp[x][y][i]) continue;
			dp[x][y][i] = true;
			UL t = G[x][y];
			if (G[x][y + 1] == nx[t][i][0])
				Q.push({ {x, y + 1}, nx[t][i][1] });
			if (G[x - 1][y] == nx[t][(i + 3) & 3][0])
				Q.push({ {x - 1, y}, (nx[t][(i + 3) & 3][1] + 1) & 3 });
			if (G[x][y - 1] == nx[t][(i + 2) & 3][0])
				Q.push({ {x, y - 1}, (nx[t][(i + 2) & 3][1] + 2) & 3 });
			if (G[x + 1][y] == nx[t][(i + 1) & 3][0])
				Q.push({ {x + 1, y}, (nx[t][(i + 1) & 3][1] + 3) & 3 });
		}
		bool ans = false;
		rep(i, 4) if (dp[W][H][i]) ans = true;

		cout << (ans ? "YES" : "NO") << endl;
	}

	Problem();
};
int main() {
	unique_ptr<Problem> p(new Problem());
	p->Solve();
	return 0;
}
Problem::Problem() {
	cout << fixed << setprecision(10);
}

C++: // I SEint YOU...! 
#include<iostream>
#include<vector>
#include<algorithm>
#include<functional>
#include<queue>
#include<chrono>
#include<iomanip>
#include<map>
#include<set>
using namespace std;
void init_io(){
  cin.tie(0);
  ios::sync_with_stdio(false);
  cout << setprecision(10);
}
string d[110];
bool used[110][110]={};
signed main(){
  init_io();
  int h,w;
  int arr[]={6,3,1,4},idx;
  cin >> h >> w;
  for(int i=0;i<h;i++){
    cin >> d[i];
    if(i%4==0) idx = 0;
    else idx = 2;
    for(int j=0;j<w;j++){
      if(i%2==0){
        if((d[i][j]-'0')!=arr[idx]){
          d[i][j]='#';
        }
        if(i%4==0) idx = (idx+1)%4;
        else idx = (idx+3)%4;
      }else{
        if((i+1)%4==0&&(d[i][j]-'0')!=5){
          d[i][j] = '#';
        }else if((i+1)%4!=0&&(d[i][j]-'0')!=2){
          d[i][j] = '#';
        }
      }
    }
  }
  queue<pair<int,int> > que;
  que.push(pair<int,int>(0,0));
  int vx[]={1,0,-1,0},vy[]={0,1,0,-1};
  while(!que.empty()){
    pair<int,int> tmp = que.front();
    que.pop();
    int x = tmp.first, y=tmp.second;
    if(used[x][y]) continue;
    used[x][y] = true;
    for(int i=0;i<4;i++){
      int nx = x + vx[i];
      int ny = y + vy[i];
      if(nx>=0&&ny>=0&&nx<h&&ny<w){
        if(d[nx][ny]!='#'){
          que.push(pair<int,int>(nx,ny));
        }
      }
    }
  }
  if(used[h-1][w-1]){
    cout <<"YES\n";
  }else{
    cout <<"NO\n";
  }
}

C++: #include <bits/stdc++.h>
using namespace std;
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;}
using Int = long long;
const char newl = '\n';


struct Die{
  array<int, 6> s;
  int &top()   {return s[0];}
  int &south() {return s[1];}
  int &east()  {return s[2];}
  int &west()  {return s[3];}
  int &north() {return s[4];}
  int &bottom(){return s[5];}
  void roll(char c){
    //the view from above
    // N
    //W E
    // S
    string b("EWNSRL");
    int v[6][4]={{0,3,5,2},
                 {0,2,5,3},
                 {0,1,5,4},
                 {0,4,5,1},
                 {1,2,4,3},
                 {1,3,4,2}};
    for(int k=0;k<6;k++){
      if(b[k]!=c) continue;
      int t=s[v[k][0]];
      s[v[k][0]]=s[v[k][1]];
      s[v[k][1]]=s[v[k][2]];
      s[v[k][2]]=s[v[k][3]];
      s[v[k][3]]=t;
    }
  }
  using ll = long long;
  ll hash(){
    ll res=0;
    for(int i=0;i<6;i++) res=res*256+s[i];
    return res;
  }
  bool operator==(const Die &d) const{
    for(int i=0;i<6;i++) if(s[i]!=d.s[i]) return 0;
    return 1;
  }
};

vector<Die> makeDice(Die d){
  vector<Die> res;
  for(int i=0;i<6;i++){
    Die t(d);
    if(i==1) t.roll('N');
    if(i==2) t.roll('S');
    if(i==3) t.roll('S'),t.roll('S');
    if(i==4) t.roll('L');
    if(i==5) t.roll('R');
    for(int k=0;k<4;k++){
      res.push_back(t);
      t.roll('E');
    }
  }
  return res;
}


template<typename T> void drop(const T &x){cout<<x<<endl;exit(0);}

//INSERT ABOVE HERE
int dp[100][200][200];
signed main(){
  cin.tie(0);
  ios::sync_with_stdio(0);

  int h,w;
  cin>>h>>w;
  vector<string> ss(h);
  for(int i=0;i<h;i++) cin>>ss[i];

  Die d;
  d.top()='1';
  d.bottom()='6';
  d.north()='5';
  d.south()='2';
  d.east()='3';
  d.west()='4';

  auto ds=makeDice(d);
  map<array<int, 6>, int> idx;
  for(int i=0;i<(int)ds.size();i++)
    idx[ds[i].s]=i;

  memset(dp,0,sizeof(dp));
  using T = tuple<int, int, int>;
  queue<T> que;

  dp[idx[d.s]][0][0]=1;
  que.emplace(idx[d.s],0,0);

  while(!que.empty()){
    int k,i,j;
    tie(k,i,j)=que.front();que.pop();
    if(i==h-1 and j==w-1) drop("YES");
    d=ds[k];

    // cout<<k<<" "<<i<<" "<<j<<endl;

    if(i+1<h){
      int ni=i+1,nj=j;
      Die nd(d);
      nd.roll('S');
      if(nd.bottom()==ss[ni][nj] and !dp[idx[nd.s]][ni][nj]){
        dp[idx[nd.s]][ni][nj]=1;
        que.emplace(idx[nd.s],ni,nj);
      }
    }
    if(i-1>=0){
      int ni=i-1,nj=j;
      Die nd(d);
      nd.roll('N');
      if(nd.bottom()==ss[ni][nj] and !dp[idx[nd.s]][ni][nj]){
        dp[idx[nd.s]][ni][nj]=1;
        que.emplace(idx[nd.s],ni,nj);
      }
    }

    if(j+1<w){
      int ni=i,nj=j+1;
      Die nd(d);
      nd.roll('E');
      if(nd.bottom()==ss[ni][nj] and !dp[idx[nd.s]][ni][nj]){
        dp[idx[nd.s]][ni][nj]=1;
        que.emplace(idx[nd.s],ni,nj);
      }
    }
    if(j-1>=0){
      int ni=i,nj=j-1;
      Die nd(d);
      nd.roll('W');
      if(nd.bottom()==ss[ni][nj] and !dp[idx[nd.s]][ni][nj]){
        dp[idx[nd.s]][ni][nj]=1;
        que.emplace(idx[nd.s],ni,nj);
      }
    }
  }

  drop("NO");
  return 0;
}