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++: /**
 * @brief ユーザ定義リテラル
 * @author えびちゃん
 */

#ifndef H_int_literals
#define H_int_literals

#include <cstddef>
#include <cstdint>

constexpr intmax_t  operator ""_jd(unsigned long long n) { return n; }
constexpr uintmax_t operator ""_ju(unsigned long long n) { return n; }
constexpr size_t    operator ""_zu(unsigned long long n) { return n; }
constexpr ptrdiff_t operator ""_td(unsigned long long n) { return n; }

#endif  /* !defined(H_int_literals) */

/**
 * @brief 多次元 vector の作成
 * @author えびちゃん
 */

#ifndef H_make_vector
#define H_make_vector

#include <cstddef>
#include <type_traits>
#include <vector>

namespace detail {
  template <typename Tp, size_t N>
  std::vector<Tp> make_vector(
      std::vector<size_t>& sizes,
      typename std::enable_if<(N == 1), Tp const&>::type x
  ) {
    return std::vector<Tp>(sizes[0], x);
  }
  template <typename Tp, size_t N>
  auto make_vector(
      std::vector<size_t>& sizes,
      typename std::enable_if<(N > 1), Tp const&>::type x
  ) {
    size_t size = sizes[N-1];
    sizes.pop_back();
    return std::vector<decltype(make_vector<Tp, N-1>(sizes, x))>(
        size, make_vector<Tp, N-1>(sizes, x)
    );
  }
}  // detail::

template <typename Tp, size_t N>
auto make_vector(size_t const(&sizes)[N], Tp const& x = Tp()) {
  std::vector<size_t> s(N);
  for (size_t i = 0; i < N; ++i) s[i] = sizes[N-i-1];
  return detail::make_vector<Tp, N>(s, x);
}

#endif  /* !defined(H_make_vector) */

#include <cstdio>
#include <cstdint>
#include <string>
#include <vector>
#include <algorithm>
#include <utility>
#include <queue>
#include <array>
#include <tuple>

std::array<size_t, 4> const di{{-1_zu, 0, 1, 0}};
std::array<size_t, 4> const dj{{0, -1_zu, 0, 1}};

int main() {
  size_t h, w;
  scanf("%zu %zu", &h, &w);

  std::vector<std::string> s(h);
  for (auto& si: s) {
    char buf[128];
    scanf("%s", buf);
    si = buf;
  }

  std::vector<std::string> t(h, std::string(w, '.'));
  for (size_t i = 0; i < h; ++i) {
    for (size_t j = 0; j < w; ++j) {
      if (s[i][j] == '#') {
        t[i][j] = '#';
      } else if (i % 4 == 1 && s[i][j] == '2') {
        t[i][j] = '.';
      } else if (i % 4 == 3 && s[i][j] == '5') {
        t[i][j] = '.';
      } else if (j % 4 == 1 && s[i][j] == '3') {
        t[i][j] = '.';
      } else if (j % 4 == 3 && s[i][j] == '4') {
        t[i][j] = '.';
      } else if ((i+j) % 4 == 0 && s[i][j] == '6') {
        t[i][j] = '.';
      } else if ((i+j) % 4 == 2 && s[i][j] == '1') {
        t[i][j] = '.';
      } else {
        t[i][j] = '#';
      }
    }
  }

  using zahyo = std::pair<size_t, size_t>;
  auto dp = make_vector({h, w}, false);
  std::queue<zahyo> q;
  q.emplace(0, 0);
  dp[0][0] = true;
  while (!q.empty()) {
    size_t i, j;
    std::tie(i, j) = q.front();
    q.pop();

    for (size_t k = 0; k < 4; ++k) {
      size_t ni = i + di[k];
      size_t nj = j + dj[k];
      if (!(ni < h && nj < w)) continue;
      if (t[ni][nj] == '#') continue;
      if (dp[ni][nj]) continue;
      dp[ni][nj] = true;
      q.emplace(ni, nj);
    }
  }

  puts(dp[h-1][w-1]? "YES": "NO");
}