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;

#define INF_LL (int64)1e18
#define INF (int32)1e9
#define REP(i, n) for(int64 i = 0;i < (n);i++)
#define FOR(i, a, b) for(int64 i = (a);i < (b);i++)
#define all(x) x.begin(),x.end()
#define fs first
#define sc second

using int32 = int_fast32_t;
using uint32 = uint_fast32_t;
using int64 = int_fast64_t;
using uint64 = uint_fast64_t;
using PII = pair<int32, int32>;
using PLL = pair<int64, int64>;

const double eps = 1e-10;

template<typename A, typename B>inline void chmin(A &a, B b){if(a > b) a = b;}
template<typename A, typename B>inline void chmax(A &a, B b){if(a < b) a = b;}

template<typename T>
vector<T> make_v(size_t a){return vector<T>(a);}

template<typename T,typename... Ts>
auto make_v(size_t a,Ts... ts){
	return vector<decltype(make_v<T>(ts...))>(a,make_v<T>(ts...));
}

template<typename T,typename U,typename... V>
typename enable_if<is_same<T, U>::value!=0>::type
fill_v(U &u,const V... v){u=U(v...);}

template<typename T,typename U,typename... V>
typename enable_if<is_same<T, U>::value==0>::type
fill_v(U &u,const V... v){
	for(auto &e:u) fill_v<T>(e,v...);
}

int64 d[4][4] = {{6, 3, 1, 4}, {2, 3, 5, 4}, {1, 3, 6, 4}, {5, 3, 2, 4}};

int64 dx[4] = {-1, 0, 1, 0};
int64 dy[4] = {0, -1, 0, 1};
string dir = "WNES";

struct Die{
  int s[6];
  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;
  }

  bool operator<(const Die &d) const {
    return s[0] < d.s[0];
  }
};

int main(void){
	cin.tie(0);
	ios::sync_with_stdio(false);
	int64 H, W;
	cin >> H >> W;
	vector<string> f(H);
	REP(i, H) {
	  cin >> f[i];
	}
	auto d = make_v<int64>(H, W);
	fill_v<int64>(d, INF_LL);
	auto in = [&](int64 y, int64 x) {
	  return 0<=y&&y<H&&0<=x&&x<W&&(f[y][x]!='#');
	};
	using T = tuple<int64, int64, int64, Die>;
	priority_queue<T, vector<T>, greater<T>> pq;
	Die init;
	init.top() = 1; init.south() = 2; init.bottom() = 6; init.north() = 5; init.west() = 4; init.east() = 3;
	pq.emplace(0, 0, 0, init);
	d[0][0] = 0;
	while (pq.size()) {
	  int64 dd, y, x;
	  Die dice;
	  tie(dd, y, x, dice) = pq.top(); pq.pop();
	  if (d[y][x] < dd) continue;
	  REP(i, 4) {
	    int64 yy = y + dy[i], xx = x + dx[i];
	    Die nxt = dice;
	    nxt.roll(dir[i]);
	    if (!in(yy, xx) || nxt.bottom() != (f[yy][xx] - '0')) continue;
	    if (d[yy][xx] > dd+1) {
	      d[yy][xx] = dd+1;
	      pq.emplace(dd+1, yy, xx, nxt);
	    }
	  }
	}
	if (d[H-1][W-1] != INF_LL) {
    cout << "YES" << endl;
	} else {
	  cout << "NO" << endl;
	}
}

C++: #include <bits/stdc++.h>
using namespace std;
#define rep(i,n) for(int i = 0; i < (n);i++)
#define sz(x) int(x.size())
typedef long long ll;
typedef pair<int,int> P;
int dx[] = {1, 0, -1, 0};
int dy[] = {0, 1, 0, -1};
struct dice {
  int front, bottom, top;
  int d[4];

  void init(){
    top = 1;
    front = 2;
    bottom = 6;
    d[0] = front;
    d[1] = 3;
    d[2] = 5;
    d[3] = 4;
  }

  void roll(int id) {
    int tmp_t, tmp_b;
    if (id == 0) {
      tmp_t = d[2];
      tmp_b = d[0];
      d[0] = top;
      d[2] = bottom;
      top = tmp_t;
      bottom = tmp_b;
    } 
    if (id == 1) {
      tmp_t = d[3];
      tmp_b = d[1];
      d[1] = top;
      d[3] = bottom;
      top = tmp_t;
      bottom = tmp_b;
    }
    if (id == 2) {
      tmp_t = d[0];
      tmp_b = d[2];
      d[0] = bottom;
      d[2] = top;
      top = tmp_t;
      bottom = tmp_b;
    }
    if (id == 3) {
      tmp_t = d[1];
      tmp_b = d[3];
      d[1] = bottom;
      d[3] = top;
      top = tmp_t;
      bottom = tmp_b;
    }
  }

};

int main(){
  int h, w;
  cin >> h >> w;
  vector<string> s(h);
  rep(i,h) cin >> s[i];
  
  dice now;
  now.init();
  vector<vector<int>> ok(h, vector<int>(w,0));
  
  queue<pair<dice, P>> que;

  que.push(make_pair(now,make_pair(0, 0)));
  ok[0][0] = 1;

  while (!que.empty()) {
    auto p = que.front(); que.pop();
    
    for (int i = 0; i < 4; i++) {
      int x = p.second.first + dx[i], y = p.second.second + dy[i];
      if (x < 0 || y < 0 || x >= h || y >= w) continue;
      if (s[x][y] == '#') continue;
      auto tmp = p.first;
      tmp.roll(i);
      if (tmp.bottom != s[x][y] - '0') continue;
      if (ok[x][y]) continue;
      que.push(make_pair(tmp, make_pair(x, y)));
      ok[x][y] = 1;
    }
  }
  cout << (ok[h-1][w-1] ? "YES" : "NO") << endl;
  return 0;
}