#include <bits/stdc++.h>
using namespace std;
const int MX = 35;
struct Point {
  int x, y;
  Point() {}
  Point(int _x, int _y) : x(_x), y(_y) {}
  bool operator==(const Point &b) const { return x == b.x && y == b.y; }
  bool operator!=(const Point &b) const { return !(*this == b); }
};
int N, M, ip[MX][MX], op[MX][MX];
Point p(-1, -1), q;
vector<Point> ans;
vector<Point> seq;
int bad[MX][MX];
Point prv[MX][MX];
Point que[MX * MX];
int vst[MX][MX];
int fr, bk;
int dir[8][2] = {{-1, 0}, {1, 0},  {0, 1},  {0, -1},
                 {1, 1},  {1, -1}, {-1, 1}, {-1, -1}};
vector<Point> path;
void BFS(Point ed) {
  fr = bk = 0;
  memset((vst), 0, sizeof(vst));
  que[bk++] = p;
  vst[p.x][p.y] = 1;
  while (fr < bk) {
    Point u = que[fr++];
    for (int i = 0; i < 8; i++) {
      int nx = u.x + dir[i][0];
      int ny = u.y + dir[i][1];
      if (nx < 1 || ny < 1 || nx > N || ny > M) continue;
      if (bad[nx][ny]) continue;
      if (q.x == nx && q.y == ny) continue;
      if (vst[nx][ny]) continue;
      que[bk++] = Point(nx, ny);
      prv[nx][ny] = u;
      vst[nx][ny] = 1;
    }
    if (vst[ed.x][ed.y]) break;
  }
  assert(vst[ed.x][ed.y] == 1);
  path.clear();
  Point cur = ed;
  while (cur != p) {
    path.push_back(cur);
    cur = prv[cur.x][cur.y];
  }
  reverse(path.begin(), path.end());
}
void move(Point a) {
  if (ans.size()) {
    assert(a != ans.back());
  }
  ans.push_back(a);
  swap(ip[a.x][a.y], ip[p.x][p.y]);
  p = a;
}
void solve(Point ed) {
  q = Point(-1, -1);
  for (int i = 1; i <= N && q.x == -1; i++) {
    for (int j = 1; j <= M && q.x == -1; j++) {
      if (bad[i][j]) continue;
      if (p.x == i && p.y == j) continue;
      if (ip[i][j] == op[ed.x][ed.y]) q = Point(i, j);
    }
  }
  int dx = 1;
  int dy = 1;
  if (ed.x < q.x) dx = -1;
  if (ed.y < q.y) dy = -1;
  while (q != ed) {
    if (q.x != ed.x && q.y != ed.y && !bad[q.x + dx][q.y + dy]) {
      BFS(Point(q.x + dx, q.y + dy));
    } else if (q.x != ed.x && !bad[q.x + dx][q.y]) {
      BFS(Point(q.x + dx, q.y));
    } else if (q.y != ed.y && !bad[q.x][q.y + dy]) {
      BFS(Point(q.x, q.y + dy));
    } else {
      assert(false);
    }
    for (auto i : path) move(i);
    Point tmp = p;
    move(q);
    q = tmp;
  }
}
void solve_seq() {
  for (auto v : seq) {
    solve(v);
    bad[v.x][v.y] = 1;
  }
}
void solve22() {
  if (p != Point(1, 1)) {
    q = Point(-1, -1);
    BFS(Point(1, 1));
    for (auto i : path) {
      move(i);
    }
  }
  if (ip[2][2] != op[2][2]) {
    if (ip[1][2] == op[2][2]) {
      move(Point(2, 2));
      move(Point(1, 2));
    } else if (ip[2][1] == op[2][2]) {
      move(Point(2, 2));
      move(Point(2, 1));
    }
  }
  if (p != Point(1, 1)) {
    move(Point(1, 1));
  }
  if (ip[1][2] != op[1][2]) {
    move(Point(2, 1));
    move(Point(1, 2));
  }
  if (p != Point(1, 1)) {
    move(Point(1, 1));
  }
}
bool check(Point st, Point ed) {
  int dx = 0;
  int dy = 0;
  if (ed.x < st.x) dx = -1;
  if (ed.x > st.x) dx = 1;
  if (ed.y < st.y) dy = -1;
  if (ed.y > st.y) dy = 1;
  int tp[MX][MX];
  for (int i = 0; i < MX; i++)
    for (int j = 0; j < MX; j++) tp[i][j] = ip[i][j];
  ans.clear();
  while (st != ed) {
    ans.push_back(st);
    swap(tp[st.x][st.y], tp[st.x + dx][st.y + dy]);
    st.x += dx;
    st.y += dy;
  }
  ans.push_back(ed);
  int fail = 0;
  for (int i = 1; i <= N && !fail; i++)
    for (int j = 1; j <= M && !fail; j++)
      if (tp[i][j] != op[i][j]) fail = 1;
  return !fail;
}
int main() {
  int c1[MX * MX] = {0};
  int c2[MX * MX] = {0};
  scanf("%d%d", &N, &M);
  for (int i = 1; i <= N; i++) {
    for (int j = 1; j <= M; j++) {
      scanf("%d", &ip[i][j]);
      c1[ip[i][j]]++;
    }
  }
  for (int i = 1; i <= N; i++) {
    for (int j = 1; j <= M; j++) {
      scanf("%d", &op[i][j]);
      c2[op[i][j]]++;
    }
  }
  for (int i = 1; i < MX * MX; i++) {
    if (c1[i] != c2[i]) {
      puts("-1");
      return 0;
    }
  }
  if (N == 1 || M == 1) {
    vector<Point> pt;
    for (int i = 1; i <= N; i++)
      for (int j = 1; j <= M; j++) pt.push_back(Point(i, j));
    int n = pt.size();
    int ok = 0;
    for (int i = 0; i < n && !ok; i++) {
      for (int j = 0; j < n && !ok; j++) {
        if (i == j) continue;
        if (check(pt[i], pt[j])) {
          ok = 1;
        }
      }
    }
    if (ok) {
      printf("%d\n", (int)ans.size() - 1);
      for (auto i : ans) printf("%d %d\n", i.x, i.y);
    } else {
      puts("-1");
    }
  } else {
    p = Point(-1, -1);
    for (int i = 1; i <= N && p.x == -1; i++) {
      for (int j = 1; j <= M && p.x == -1; j++) {
        if (ip[i][j] == op[1][1]) {
          p = Point(i, j);
        }
      }
    }
    int x = p.x;
    int y = p.y;
    for (int j = M; j > 2; j--) {
      for (int i = N; i >= 1; i--) {
        seq.push_back(Point(i, j));
      }
    }
    for (int i = N; i > 2; i--) {
      seq.push_back(Point(i, 2));
      seq.push_back(Point(i, 1));
    }
    memset((bad), 0, sizeof(bad));
    solve_seq();
    for (int i = 1; i <= N; i++) {
      for (int j = 1; j <= M; j++) {
        if (i > 2 && j > 2 && ip[i][j] != op[i][j]) {
          assert(false);
        }
      }
    }
    solve22();
    for (int i = 1; i <= N; i++) {
      for (int j = 1; j <= M; j++) {
        if (ip[i][j] != op[i][j]) {
          assert(false);
        }
      }
    }
    assert(ans.size() <= 1000000);
    printf("%d\n", (int)ans.size());
    printf("%d %d\n", x, y);
    for (auto i : ans) printf("%d %d\n", i.x, i.y);
  }
  return 0;
}
